Repository: abel533/Mapper Branch: master Commit: 8568b9ad7317 Files: 502 Total size: 1.6 MB Directory structure: gitextract_5zdklcjy/ ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── release.yml │ └── test.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── all/ │ ├── README.md │ ├── dependencies/ │ │ ├── README.md │ │ └── pom.xml │ ├── mapper/ │ │ ├── README.md │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ └── ApiInfo.java │ └── pom.xml ├── base/ │ ├── README.md │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ ├── common/ │ │ │ ├── BaseMapper.java │ │ │ ├── ConditionMapper.java │ │ │ ├── ExampleMapper.java │ │ │ ├── IdsMapper.java │ │ │ ├── Mapper.java │ │ │ ├── Marker.java │ │ │ ├── MySqlMapper.java │ │ │ ├── RowBoundsMapper.java │ │ │ ├── SaveMapper.java │ │ │ ├── SqlServerMapper.java │ │ │ ├── base/ │ │ │ │ ├── BaseDeleteMapper.java │ │ │ │ ├── BaseInsertMapper.java │ │ │ │ ├── BaseSelectMapper.java │ │ │ │ ├── BaseUpdateMapper.java │ │ │ │ ├── delete/ │ │ │ │ │ ├── DeleteByPrimaryKeyMapper.java │ │ │ │ │ └── DeleteMapper.java │ │ │ │ ├── insert/ │ │ │ │ │ ├── InsertMapper.java │ │ │ │ │ └── InsertSelectiveMapper.java │ │ │ │ ├── select/ │ │ │ │ │ ├── ExistsWithPrimaryKeyMapper.java │ │ │ │ │ ├── SelectAllMapper.java │ │ │ │ │ ├── SelectByPrimaryKeyMapper.java │ │ │ │ │ ├── SelectCountMapper.java │ │ │ │ │ ├── SelectMapper.java │ │ │ │ │ └── SelectOneMapper.java │ │ │ │ └── update/ │ │ │ │ ├── UpdateByPrimaryKeyMapper.java │ │ │ │ └── UpdateByPrimaryKeySelectiveMapper.java │ │ │ ├── condition/ │ │ │ │ ├── DeleteByConditionMapper.java │ │ │ │ ├── SelectByConditionMapper.java │ │ │ │ ├── SelectCountByConditionMapper.java │ │ │ │ ├── UpdateByConditionMapper.java │ │ │ │ └── UpdateByConditionSelectiveMapper.java │ │ │ ├── example/ │ │ │ │ ├── DeleteByExampleMapper.java │ │ │ │ ├── SelectByExampleMapper.java │ │ │ │ ├── SelectCountByExampleMapper.java │ │ │ │ ├── SelectOneByExampleMapper.java │ │ │ │ ├── UpdateByExampleMapper.java │ │ │ │ └── UpdateByExampleSelectiveMapper.java │ │ │ ├── ids/ │ │ │ │ ├── DeleteByIdsMapper.java │ │ │ │ └── SelectByIdsMapper.java │ │ │ ├── progressive/ │ │ │ │ └── ProgressiveMapper.java │ │ │ ├── rowbounds/ │ │ │ │ ├── SelectByConditionRowBoundsMapper.java │ │ │ │ ├── SelectByExampleRowBoundsMapper.java │ │ │ │ └── SelectRowBoundsMapper.java │ │ │ ├── special/ │ │ │ │ ├── InsertListMapper.java │ │ │ │ └── InsertUseGeneratedKeysMapper.java │ │ │ └── sqlserver/ │ │ │ ├── InsertMapper.java │ │ │ └── InsertSelectiveMapper.java │ │ └── provider/ │ │ ├── ConditionProvider.java │ │ ├── ExampleProvider.java │ │ ├── IdsProvider.java │ │ ├── SaveProvider.java │ │ ├── SpecialProvider.java │ │ ├── SqlServerProvider.java │ │ └── base/ │ │ ├── BaseDeleteProvider.java │ │ ├── BaseInsertProvider.java │ │ ├── BaseSelectProvider.java │ │ └── BaseUpdateProvider.java │ └── test/ │ ├── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ ├── base/ │ │ │ ├── BaseTest.java │ │ │ ├── Country.java │ │ │ ├── CountryMapper.java │ │ │ ├── CreateDB.sql │ │ │ ├── delete/ │ │ │ │ ├── DeleteByPrimaryKeyMapperTest.java │ │ │ │ ├── SafeDeleteByFieldTest.java │ │ │ │ └── SafeDeleteByMethodTest.java │ │ │ ├── genid/ │ │ │ │ ├── Country.java │ │ │ │ ├── CountryMapper.java │ │ │ │ ├── CreateDB.sql │ │ │ │ ├── InsertGenIdTest.java │ │ │ │ ├── SimpleGenId.java │ │ │ │ ├── UUIdGenId.java │ │ │ │ ├── User.java │ │ │ │ ├── UserMapper.java │ │ │ │ └── mybatis-config.xml │ │ │ ├── mybatis-config.xml │ │ │ └── update/ │ │ │ ├── SafeUpdateByFieldTest.java │ │ │ └── SafeUpdateByMethodTest.java │ │ ├── cache/ │ │ │ ├── CacheTest.java │ │ │ ├── CountryCacheMapper.java │ │ │ ├── CountryCacheRefMapper.java │ │ │ ├── CountryCacheRefMapper.xml │ │ │ ├── CountryCacheWithXmlMapper.java │ │ │ ├── CountryCacheWithXmlMapper.xml │ │ │ └── mybatis-config-cache.xml │ │ ├── defaultenumtypehandler/ │ │ │ ├── CreateDB.sql │ │ │ ├── DefaultEnumTypeHandlerTest.java │ │ │ ├── Dict.java │ │ │ ├── DictTypeHandler.java │ │ │ ├── LockDictEnum.java │ │ │ ├── StateDictEnum.java │ │ │ ├── User.java │ │ │ ├── UserMapper.java │ │ │ └── mybatis-config-defaultenumtypehandler.xml │ │ ├── entity/ │ │ │ └── model/ │ │ │ └── CountryExample.java │ │ ├── generatedvalue/ │ │ │ ├── CreateDB.sql │ │ │ ├── GeneratedValueTest.java │ │ │ ├── UserAutoIncrement.java │ │ │ ├── UserAutoIncrementIdentity.java │ │ │ ├── UserAutoIncrementIdentityMapper.java │ │ │ ├── UserAutoIncrementMapper.java │ │ │ ├── UserSqlAfter.java │ │ │ ├── UserSqlAfterMapper.java │ │ │ └── mybatis-config-keysql-mysql.xml │ │ ├── helper/ │ │ │ ├── CamelCaseTest.java │ │ │ ├── FieldHelperTest.java │ │ │ ├── FieldTest.java │ │ │ └── MultipleMapperProviderTest.java │ │ ├── hsqldb/ │ │ │ ├── HsqldbMapper.java │ │ │ └── HsqldbProvider.java │ │ ├── issues/ │ │ │ ├── _216_datetime/ │ │ │ │ ├── CreateDB.sql │ │ │ │ ├── DateTimeTest.java │ │ │ │ ├── TimeModel.java │ │ │ │ ├── TimeModel2.java │ │ │ │ ├── TimeModel2Mapper.java │ │ │ │ ├── TimeModel3.java │ │ │ │ ├── TimeModel3Mapper.java │ │ │ │ ├── TimeModelMapper.java │ │ │ │ └── mybatis-config-timestamp.xml │ │ │ └── package-info.java │ │ ├── keysql/ │ │ │ ├── CreateDB.sql │ │ │ ├── KeySqlTest.java │ │ │ ├── UserAutoIncrement.java │ │ │ ├── UserAutoIncrementIdentity.java │ │ │ ├── UserAutoIncrementIdentityMapper.java │ │ │ ├── UserAutoIncrementMapper.java │ │ │ ├── UserSqlAfter.java │ │ │ ├── UserSqlAfterMapper.java │ │ │ ├── UserSqlBefore.java │ │ │ ├── UserSqlBeforeMapper.java │ │ │ └── mybatis-config-keysql-mysql.xml │ │ ├── mapper/ │ │ │ ├── CachedCountryMapper.java │ │ │ ├── Country2Mapper.java │ │ │ ├── CountryIMapper.java │ │ │ ├── CountryJDBCMapper.java │ │ │ ├── CountryMapper.java │ │ │ ├── CountryMultipleMapper.java │ │ │ ├── CountryTMapper.java │ │ │ ├── CountryVersionMapper.java │ │ │ ├── JDBCMapper.java │ │ │ ├── MultipleCommonMapper.java │ │ │ ├── MybatisHelper.java │ │ │ ├── TbUserLogicDeleteMapper.java │ │ │ ├── TbUserMapper.java │ │ │ ├── UserInfoAbleMapper.java │ │ │ ├── UserInfoMapMapper.java │ │ │ ├── UserInfoMapper.java │ │ │ ├── UserLogin2Mapper.java │ │ │ └── UserLoginMapper.java │ │ ├── model/ │ │ │ ├── BaseLogicDelete.java │ │ │ ├── Country.java │ │ │ ├── Country2.java │ │ │ ├── CountryExample.java │ │ │ ├── CountryI.java │ │ │ ├── CountryJDBC.java │ │ │ ├── CountryT.java │ │ │ ├── CountryVersion.java │ │ │ ├── Entity.java │ │ │ ├── TbUser.java │ │ │ ├── TbUserLogicDelete.java │ │ │ ├── UserInfo.java │ │ │ ├── UserInfoAble.java │ │ │ ├── UserInfoMap.java │ │ │ ├── UserLogin.java │ │ │ ├── UserLogin2.java │ │ │ ├── UserLogin2Key.java │ │ │ └── UserParent.java │ │ ├── rawresultmap/ │ │ │ ├── CreateDB.sql │ │ │ ├── RawResultMapTest.java │ │ │ ├── User.java │ │ │ ├── UserMapper.java │ │ │ ├── UserMapper.xml │ │ │ └── mybatis-config-rawresultmap.xml │ │ ├── test/ │ │ │ ├── able/ │ │ │ │ └── TestBasicAble.java │ │ │ ├── country/ │ │ │ │ ├── TestCache.java │ │ │ │ ├── TestDeleteByPrimaryKey.java │ │ │ │ ├── TestExistsWithPrimaryKey.java │ │ │ │ ├── TestInsert.java │ │ │ │ ├── TestInsertSelective.java │ │ │ │ ├── TestSelect.java │ │ │ │ ├── TestSelectAll.java │ │ │ │ ├── TestSelectByPrimaryKey.java │ │ │ │ ├── TestSelectCount.java │ │ │ │ ├── TestSelectOne.java │ │ │ │ ├── TestUpdateByPrimaryKey.java │ │ │ │ └── TestUpdateByPrimaryKeySelective.java │ │ │ ├── country2/ │ │ │ │ ├── TestInsert.java │ │ │ │ └── TestInsertSelective.java │ │ │ ├── example/ │ │ │ │ ├── TestDeleteByExample.java │ │ │ │ ├── TestExampleBuilder.java │ │ │ │ ├── TestSelectByExample.java │ │ │ │ ├── TestSelectCountByExample.java │ │ │ │ ├── TestSelectOneByExample.java │ │ │ │ ├── TestUpdateByExample.java │ │ │ │ └── TestUpdateByExampleSelective.java │ │ │ ├── identity/ │ │ │ │ └── TestIndentity.java │ │ │ ├── ids/ │ │ │ │ └── TestIds.java │ │ │ ├── jdbc/ │ │ │ │ └── TestJDBC.java │ │ │ ├── logic/ │ │ │ │ └── TestLogicDelete.java │ │ │ ├── mysql/ │ │ │ │ └── TestMysql.java │ │ │ ├── othres/ │ │ │ │ ├── StyleTest.java │ │ │ │ └── TestDelimiter.java │ │ │ ├── rowbounds/ │ │ │ │ └── TestSelectRowBounds.java │ │ │ ├── transientc/ │ │ │ │ └── TestTransient.java │ │ │ └── user/ │ │ │ ├── TestBasic.java │ │ │ ├── TestDelete.java │ │ │ ├── TestMap.java │ │ │ ├── TestUserLogin.java │ │ │ └── TestUserLogin2.java │ │ ├── typehandler/ │ │ │ ├── Address.java │ │ │ ├── AddressTypeHandler.java │ │ │ ├── CreateDB.sql │ │ │ ├── StateEnum.java │ │ │ ├── StateEnumTypeHandler.java │ │ │ ├── TypeHandlerTest.java │ │ │ ├── TypeHandlerTest2.java │ │ │ ├── User.java │ │ │ ├── User2.java │ │ │ ├── User2Mapper.java │ │ │ ├── UserMapper.java │ │ │ ├── mybatis-config-typehandler.xml │ │ │ └── mybatis-config-typehandler2.xml │ │ └── version/ │ │ ├── CreateDB.sql │ │ ├── UserInt.java │ │ ├── UserIntMapper.java │ │ ├── UserTimestamp.java │ │ ├── UserTimestampMapper.java │ │ ├── VersionTest.java │ │ └── mybatis-config-version.xml │ └── resources/ │ ├── CachedCountryMapper.xml │ ├── CreateDB.sql │ ├── logback.xml │ └── mybatis-java.xml ├── core/ │ ├── README.md │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ ├── LogicDeleteException.java │ │ ├── MapperException.java │ │ ├── annotation/ │ │ │ ├── ColumnType.java │ │ │ ├── KeySql.java │ │ │ ├── LogicDelete.java │ │ │ ├── NameStyle.java │ │ │ ├── Order.java │ │ │ ├── RegisterMapper.java │ │ │ └── Version.java │ │ ├── code/ │ │ │ ├── IdentityDialect.java │ │ │ ├── ORDER.java │ │ │ └── Style.java │ │ ├── entity/ │ │ │ ├── Condition.java │ │ │ ├── Config.java │ │ │ ├── EntityColumn.java │ │ │ ├── EntityField.java │ │ │ ├── EntityTable.java │ │ │ ├── Example.java │ │ │ ├── IDynamicTableName.java │ │ │ └── SqlsCriteria.java │ │ ├── genid/ │ │ │ ├── GenId.java │ │ │ └── GenIdUtil.java │ │ ├── gensql/ │ │ │ └── GenSql.java │ │ ├── mapperhelper/ │ │ │ ├── EntityHelper.java │ │ │ ├── FieldHelper.java │ │ │ ├── MapperHelper.java │ │ │ ├── MapperTemplate.java │ │ │ ├── SelectKeyGenerator.java │ │ │ ├── SelectKeyHelper.java │ │ │ ├── SqlHelper.java │ │ │ └── resolve/ │ │ │ ├── DefaultEntityResolve.java │ │ │ └── EntityResolve.java │ │ ├── provider/ │ │ │ └── EmptyProvider.java │ │ ├── session/ │ │ │ └── Configuration.java │ │ ├── util/ │ │ │ ├── Assert.java │ │ │ ├── MetaObjectUtil.java │ │ │ ├── MsUtil.java │ │ │ ├── OGNL.java │ │ │ ├── SimpleTypeUtil.java │ │ │ ├── SqlReservedWords.java │ │ │ ├── Sqls.java │ │ │ └── StringUtil.java │ │ └── version/ │ │ ├── DefaultNextVersion.java │ │ ├── NextVersion.java │ │ ├── VersionException.java │ │ └── VersionUtil.java │ └── test/ │ └── java/ │ └── tk/ │ └── mybatis/ │ └── mapper/ │ ├── annotation/ │ │ ├── ColumnTest.java │ │ ├── ColumnTypeTest.java │ │ ├── IdTest.java │ │ ├── KeySqlTest.java │ │ ├── NameStyleTest.java │ │ ├── RegisterMapperTest.java │ │ ├── TableTest.java │ │ └── VersionTest.java │ ├── mapperhelper/ │ │ ├── ComplexEntityTest.java │ │ ├── FieldHelperTest.java │ │ └── SqlHelperTest.java │ └── util/ │ └── StringUtilTest.java ├── extra/ │ ├── README.md │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ └── additional/ │ │ ├── aggregation/ │ │ │ ├── AggregateCondition.java │ │ │ ├── AggregateType.java │ │ │ ├── AggregationMapper.java │ │ │ └── AggregationProvider.java │ │ ├── delete/ │ │ │ ├── DeleteByPropertyMapper.java │ │ │ └── DeletePropertyProvider.java │ │ ├── dialect/ │ │ │ └── oracle/ │ │ │ ├── InsertListMapper.java │ │ │ ├── OracleMapper.java │ │ │ └── OracleProvider.java │ │ ├── idlist/ │ │ │ ├── DeleteByIdListMapper.java │ │ │ ├── IdListMapper.java │ │ │ ├── IdListProvider.java │ │ │ └── SelectByIdListMapper.java │ │ ├── insert/ │ │ │ ├── InsertListMapper.java │ │ │ └── InsertListProvider.java │ │ ├── select/ │ │ │ ├── SelectByPropertyMapper.java │ │ │ ├── SelectPropertyProvider.java │ │ │ ├── SelectSpecifyColumnsMapper.java │ │ │ └── SelectSpecifyColumnsProvider.java │ │ ├── update/ │ │ │ ├── batch/ │ │ │ │ ├── BatchUpdateMapper.java │ │ │ │ ├── BatchUpdateProvider.java │ │ │ │ └── BatchUpdateSelectiveMapper.java │ │ │ ├── differ/ │ │ │ │ ├── UpdateByDifferMapper.java │ │ │ │ └── UpdateByDifferProvider.java │ │ │ └── force/ │ │ │ ├── UpdateByPrimaryKeySelectiveForceMapper.java │ │ │ └── UpdateByPrimaryKeySelectiveForceProvider.java │ │ └── upsert/ │ │ ├── BatchUpsertMapper.java │ │ ├── BatchUpsertProvider.java │ │ ├── UpsertMapper.java │ │ └── UpsertProvider.java │ └── test/ │ ├── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ └── additional/ │ │ ├── BaseTest.java │ │ ├── Country.java │ │ ├── CountryMapper.java │ │ ├── CreateDB.sql │ │ ├── aggregation/ │ │ │ ├── AggregationHumpTest.java │ │ │ ├── AggregationMapperTest.java │ │ │ ├── CreateDB.sql │ │ │ ├── User.java │ │ │ ├── UserHump.java │ │ │ ├── UserHumpMapper.java │ │ │ ├── UserMapper.java │ │ │ └── mybatis-config.xml │ │ ├── delete/ │ │ │ ├── Course.java │ │ │ ├── CourseMapper.java │ │ │ ├── CreateDB.sql │ │ │ ├── DeleteByPropertyMapperTest.java │ │ │ └── mybatis-config.xml │ │ ├── dialect/ │ │ │ └── oracle/ │ │ │ ├── CreateDB.sql │ │ │ ├── DemoCountry.java │ │ │ ├── DemoCountryMapper.java │ │ │ ├── OracleTest.java │ │ │ └── mybatis-config.xml │ │ ├── idlist/ │ │ │ ├── ABaseMapper.java │ │ │ ├── CountryMapper.java │ │ │ ├── IdListMapperTest.java │ │ │ └── mybatis-config.xml │ │ ├── insertlist/ │ │ │ ├── CreateDB.sql │ │ │ ├── InsertListMapperTest.java │ │ │ ├── UUIdGenId.java │ │ │ ├── User.java │ │ │ ├── UserMapper.java │ │ │ └── mybatis-config.xml │ │ ├── mybatis-config.xml │ │ ├── select/ │ │ │ ├── Book.java │ │ │ ├── BookMapper.java │ │ │ ├── CreateDB.sql │ │ │ ├── SelectByPropertyMapperTest.java │ │ │ └── mybatis-config.xml │ │ └── update/ │ │ ├── differ/ │ │ │ ├── CountryMapper.java │ │ │ ├── UpdateByDifferMapperTest.java │ │ │ └── mybatis-config.xml │ │ └── force/ │ │ ├── CountryInt.java │ │ ├── CountryIntMapper.java │ │ ├── CreateDB.sql │ │ ├── UpdateByPrimaryKeySelectiveForceTest.java │ │ └── mybatis-config.xml │ └── resources/ │ └── logback.xml ├── generator/ │ ├── README.md │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── tk/ │ │ │ └── mybatis/ │ │ │ └── mapper/ │ │ │ └── generator/ │ │ │ ├── FalseMethodPlugin.java │ │ │ ├── MapperCommentGenerator.java │ │ │ ├── MapperPlugin.java │ │ │ ├── TemplateFilePlugin.java │ │ │ ├── TkMyBatis3Impl.java │ │ │ ├── TkMyBatis3SimpleImpl.java │ │ │ ├── file/ │ │ │ │ ├── GenerateByListTemplateFile.java │ │ │ │ └── GenerateByTemplateFile.java │ │ │ ├── formatter/ │ │ │ │ ├── FreemarkerTemplateFormatter.java │ │ │ │ ├── ListTemplateFormatter.java │ │ │ │ └── TemplateFormatter.java │ │ │ └── model/ │ │ │ ├── ColumnField.java │ │ │ ├── TableClass.java │ │ │ └── TableColumnBuilder.java │ │ └── resources/ │ │ └── generator/ │ │ ├── mapper.ftl │ │ ├── mapperXml.ftl │ │ ├── test-all.ftl │ │ └── test-one.ftl │ └── test/ │ ├── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ └── generator/ │ │ └── Generator.java │ └── resources/ │ ├── CreateDB.sql │ └── generatorConfig.xml ├── pom.xml ├── solon-plugin/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── tk/ │ │ │ └── mybatis/ │ │ │ └── solon/ │ │ │ ├── TkMapperAdapterFactory.java │ │ │ ├── TkMapperMybatisAdapter.java │ │ │ └── XPluginImpl.java │ │ └── resources/ │ │ └── META-INF/ │ │ └── solon/ │ │ └── mybatis-tkmapper-solon-plugin.properties │ └── test/ │ ├── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── solon/ │ │ └── test/ │ │ ├── TkMapperTest.java │ │ ├── conf/ │ │ │ └── TestConfig.java │ │ ├── entity/ │ │ │ └── User.java │ │ ├── mapper/ │ │ │ └── UserMapper.java │ │ └── service/ │ │ └── TkMapperServiceTest.java │ └── resources/ │ ├── app.yml │ └── mapper/ │ └── UserMapper.xml ├── spring/ │ ├── README.md │ ├── license.txt │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── spring/ │ │ ├── annotation/ │ │ │ ├── BaseProperties.java │ │ │ ├── MapperScan.java │ │ │ ├── MapperScannerRegistrar.java │ │ │ └── MapperScans.java │ │ └── mapper/ │ │ ├── ClassPathMapperScanner.java │ │ ├── MapperFactoryBean.java │ │ ├── MapperScannerConfigurer.java │ │ └── SpringBootBindUtil.java │ └── test/ │ ├── java/ │ │ └── tk/ │ │ └── mybatis/ │ │ └── mapper/ │ │ ├── annotation/ │ │ │ ├── Country.java │ │ │ ├── CountryMapper.java │ │ │ └── SpringAnnotationTest.java │ │ ├── configuration/ │ │ │ ├── Country.java │ │ │ ├── CountryMapper.java │ │ │ ├── CreateDB.sql │ │ │ ├── SpringConfigTest.java │ │ │ └── spring.xml │ │ └── xml/ │ │ ├── Country.java │ │ ├── CountryMapper.java │ │ ├── CreateDB.sql │ │ ├── SpringXmlTest.java │ │ └── spring.xml │ └── resources/ │ └── logback.xml ├── spring-boot-starter/ │ ├── README.md │ ├── mapper-spring-boot-autoconfigure/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── tk/ │ │ │ └── mybatis/ │ │ │ └── mapper/ │ │ │ └── autoconfigure/ │ │ │ ├── ConfigurationCustomizer.java │ │ │ ├── MapperAutoConfiguration.java │ │ │ ├── MapperCacheDisabler.java │ │ │ ├── MapperProperties.java │ │ │ ├── MybatisDependsOnDatabaseInitializationDetector.java │ │ │ ├── MybatisLanguageDriverAutoConfiguration.java │ │ │ ├── MybatisProperties.java │ │ │ ├── SpringBootVFS.java │ │ │ └── SqlSessionFactoryBeanCustomizer.java │ │ └── resources/ │ │ └── META-INF/ │ │ └── spring/ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ ├── mapper-spring-boot-samples/ │ │ ├── mapper-spring-boot-sample-annotation/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── tk/ │ │ │ │ └── mybatis/ │ │ │ │ └── sample/ │ │ │ │ ├── SampleMapperApplication.java │ │ │ │ ├── domain/ │ │ │ │ │ └── Country.java │ │ │ │ └── mapper/ │ │ │ │ └── CountryMapper.java │ │ │ └── resources/ │ │ │ ├── application.properties │ │ │ ├── import.sql │ │ │ └── logback.xml │ │ ├── mapper-spring-boot-sample-xml/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── tk/ │ │ │ │ └── mybatis/ │ │ │ │ └── sample/ │ │ │ │ ├── SampleXmlApplication.java │ │ │ │ ├── domain/ │ │ │ │ │ └── Country.java │ │ │ │ └── mapper/ │ │ │ │ ├── BaseMapper.java │ │ │ │ └── CountryMapper.java │ │ │ └── resources/ │ │ │ ├── application.yml │ │ │ ├── import.sql │ │ │ ├── logback.xml │ │ │ ├── mybatis-config.xml │ │ │ └── tk/ │ │ │ └── mybatis/ │ │ │ └── sample/ │ │ │ └── mapper/ │ │ │ └── CountryMapper.xml │ │ └── pom.xml │ ├── mapper-spring-boot-starter/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── resources/ │ │ └── META-INF/ │ │ └── spring.provides │ └── pom.xml └── weekend/ ├── README.md ├── pom.xml └── src/ ├── main/ │ └── java/ │ └── tk/ │ └── mybatis/ │ └── mapper/ │ └── weekend/ │ ├── Fn.java │ ├── SqlCriteriaHelper.java │ ├── Weekend.java │ ├── WeekendCriteria.java │ ├── WeekendSqls.java │ ├── WeekendSqlsUtils.java │ └── reflection/ │ ├── ReflectionOperationException.java │ └── Reflections.java └── test/ ├── java/ │ └── tk/ │ └── mybatis/ │ └── mapper/ │ └── weekend/ │ ├── MybatisHelper.java │ ├── SqlCriteriaHelperTest.java │ ├── UserMapperTest.java │ ├── WeekendSqlsTest.java │ ├── WeekendSqlsUtilsTest.java │ ├── entity/ │ │ ├── Country.java │ │ └── User.java │ └── mapper/ │ ├── CountryMapper.java │ └── UserMapper.java └── resources/ ├── CreateDB.sql ├── logback.xml └── mybatis-java.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: [ 'https://mybatis.io/donates.html' ] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/workflows/release.yml ================================================ name: Publish package to the Maven Central Repository on: push: tags: [ "*" ] permissions: contents: read jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Maven Central Repository uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' cache: maven server-id: central server-username: OSSRH_USERNAME server-password: OSSRH_TOKEN - id: install-secret-key name: Install gpg secret key run: | cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import gpg --list-secret-keys --keyid-format LONG - name: Publish package env: OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} run: mvn --batch-mode --errors -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} -P release clean deploy ================================================ FILE: .github/workflows/test.yml ================================================ name: Maven test on: pull_request: types: [ opened, reopened, edited ] push: branches: [ develop, master ] permissions: contents: read jobs: mvn_verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Maven Central Repository uses: actions/setup-java@v2 with: java-version: '17' distribution: 'adopt' - name: Run the Maven verify phase run: mvn --batch-mode --update-snapshots test ================================================ FILE: .gitignore ================================================ # Maven # target/ .flattened-pom.xml # IDEA # .idea/ *.iml # Eclipse # .settings/ .classpath .project ================================================ FILE: .gitmodules ================================================ [submodule "wiki"] path = wiki url = https://github.com/abel533/Mapper.wiki.git ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014-2017 abel533@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # MyBatis 通用 Mapper6 来了🎉🎉🎉 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper) 通用Mapper都可以极大的方便开发人员。可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方法。 极其方便的使用MyBatis单表的增删改查。 支持单表操作,不支持通用的多表联合查询。 ## 版本匹配说明 不同分支支持不同的 Spring Boot 版本,请根据项目实际情况选择对应分支: | 分支 | Spring Boot 版本 | JDK 版本 | Mapper 版本 | |------|------------------|----------|-------------| | master | Spring Boot 4.x | JDK 17+ | 6.0.0+ | | 5.x | Spring Boot 3.x | JDK 17+ | 5.0.0 | | 4.3.x | Spring Boot 2.x | JDK 8+ | 4.3.x | ## 基于 JDK 17 + Jakarta JPA 注解 + Spring Boot 4 配置完全兼容,需要使用新版本的 JPA 注解,同步更新(copy) mybatis-spring 4.0.0 和 mybatis-spring-boot-starter 4.0.0。 此次更新主要是依赖的更新,适配最新的 Spring Boot 4.0.2,提供更好的兼容性和稳定性。 ```xml tk.mybatis mapper 6.0.0 ``` ## 推荐新版本 mybatis-mapper 如果你要在新项目中使用,可以看看新版本的 mybatis-mapper,完全作为 mybatis 扩展存在, 不修改 mybatis, mybatis-spring, mybatis-spring-boot-starter 任何代码,不需要额外配置,可以快速上手。 - mybatis-mapper: https://github.com/mybatis-mapper/mapper - mybatis-mapper 文档: https://mapper.mybatis.io - [mybatis-mapper 快速入门](https://mapper.mybatis.io/docs/1.getting-started.html#%E4%BB%8B%E7%BB%8D) ## [**快速入门 - MyBatis 为什么需要通用 Mapper ?**](https://blog.csdn.net/isea533/article/details/83045335) 简介: 在早期项目文档中有过类似主题的内容,但是最近我自己看文档的时候发现一个问题,文档虽然很详细,但是并不适合初次接触的人。为了方便第一次听说,第一次尝试的开发人员了解通用 Mapper,补充此文档。 强烈建议初学者阅读本文,先从整体上了解 通用 Mapper,然后再通过下面的文档更深入的了解。 ## [**通用 Mapper 进阶实例:为什么好久都没更新了?**](https://blog.csdn.net/isea533/article/details/104776347) 通过本文,希望读者能有收获,能根据自己的需要设计通用方法,不要只是为了偷懒将自己局限在已有的通用方法中。大而全的通用方法不一定适合自己,根据自己需要选择和设计的通用方法才更满足自己的需要。 ## 项目文档 - [文档 - Gitee](https://gitee.com/free/Mapper/wikis/Home) - [文档 - GitHub](https://github.com/abel533/Mapper/wiki) - [JavaDoc](https://apidoc.gitee.com/free/Mapper/) - [更新日志 - Gitee](https://gitee.com/free/Mapper/wikis/changelog) - [更新日志 - GitHub](https://github.com/abel533/Mapper/wiki/changelog) ## 微信公众号 ## 作者信息 MyBatis 工具网站:[https://mybatis.io](https://mybatis.io) 作者博客:http://blog.csdn.net/isea533 ,http://blog.mybatis.io 作者邮箱:abel533@gmail.com 推荐使用Mybatis分页插件:[PageHelper分页插件](https://github.com/pagehelper/Mybatis-PageHelper) ## 《MyBatis 从入门到精通》 ![MyBatis 从入门到精通](https://github.com/mybatis-book/book/raw/master/book.png) ### 简介 本书中从一个简单的 MyBatis 查询入手,搭建起学习 MyBatis 的基础开发环境。 通过全面的示例代码和测试讲解了在 MyBatis XML 方式和注解方式中进行增、删、改、查操作的基本用法,介绍了动态 SQL 在不同方面的应用以及在使用过程中的最佳实践方案。 针对 MyBatis 高级映射、存储过程和类型处理器提供了丰富的示例,通过自下而上的方法使读者更好地理解和掌握MyBatis 的高级用法,同时针对 MyBatis 的代码生成器提供了详细的配置介绍。 此外,本书还提供了缓存配置、插件开发、Spring、Spring Boot 集成的详细内容。 最后通过介绍 Git 和 GitHub 让读者了解MyBatis 开源项目,通过对 MyBatis 源码和测试用例的讲解让读者更好掌握 MyBatis。 ### 购买地址: - [京东](https://item.jd.com/12103309.html) ### 相关介绍 - CSDN博客:http://blog.csdn.net/isea533/article/details/73555400 - GitHub项目:https://github.com/mybatis-book/book ================================================ FILE: all/README.md ================================================ # Mybatis 通用 Mapper3 适配 为了帮助用户从通用 Mapper 3.x 过渡到 4.x 和以后的版本,增加本项目。 本项目下面提供了两个子模块,基于 Maven 依赖传递的 **dependencies** 和基于 maven-shade-plugin 打包为一个大 jar 包的 **mapper** 项目。 **并且本项目下面的 jar 的 Maven 为 tk.mybtis:mapper,也就是从 mapper 3.x 升级到 4.x 的时候可以只改版本号。** ================================================ FILE: all/dependencies/README.md ================================================ # Mybatis 通用 Mapper Jar 集成 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-all-dependencies/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-all-dependencies) 本项目默认集成了 mapper-core, mapper-extra, mapper-generator, mapper-spring, mapper-weekend 项目。 使用时,只需要添加 mapper-all 的依赖即可。 ```xml tk.mybatis mapper-all-dependencies 版本号 ``` 引入后会自动引入其他依赖。 可以通过在 pom 中增加下面对应的属性来修改依赖的版本号: ```xml 4.0.0-SNAPSHOT 1.0.0-SNAPSHOT 1.0.0-SNAPSHOT 1.1.3-SNAPSHOT 1.0.0-SNAPSHOT ``` > 上面具体版本号只是示例,默认不需要自己设置。 ================================================ FILE: all/dependencies/pom.xml ================================================ 4.0.0 tk.mybatis mapper-all ${revision} mapper-all-dependencies jar dependencies Mybatis 通用 Mapper Jar 集成 tk.mybatis mapper-core tk.mybatis mapper-base tk.mybatis mapper-extra tk.mybatis mapper-spring tk.mybatis mapper-weekend tk.mybatis mapper-generator ================================================ FILE: all/mapper/README.md ================================================ # Mybatis 通用 Mapper Jar 集成 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper) 本项目默认集成了 mapper-core, mapper-extra, mapper-generator, mapper-spring, mapper-weekend 项目。 使用时,只需要添加 mapper 的依赖即可。 ```xml tk.mybatis mapper 版本号 ``` 引入该依赖时不会引入传递依赖。 ================================================ FILE: all/mapper/pom.xml ================================================ 4.0.0 tk.mybatis mapper-all ${revision} mapper jar mapper Mybatis 通用 Mapper Jar 集成 jakarta.persistence jakarta.persistence-api tk.mybatis mapper-core true tk.mybatis mapper-base true tk.mybatis mapper-extra true tk.mybatis mapper-spring true tk.mybatis mapper-weekend true tk.mybatis mapper-generator true org.apache.maven.plugins maven-shade-plugin 3.6.0 package shade false true tk.mybatis:mapper-core tk.mybatis:mapper-base tk.mybatis:mapper-extra tk.mybatis:mapper-spring tk.mybatis:mapper-weekend tk.mybatis:mapper-generator ================================================ FILE: all/mapper/src/main/java/tk/mybatis/mapper/ApiInfo.java ================================================ package tk.mybatis.mapper; /** * Java Doc 内容请通过各个独立项目进行查看 * * @author liuzh */ public class ApiInfo { } ================================================ FILE: all/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-all pom mapper-all Mybatis 通用 Mapper3 适配 mapper dependencies tk.mybatis mapper-core ${project.version} compile tk.mybatis mapper-base ${project.version} compile tk.mybatis mapper-extra ${project.version} compile tk.mybatis mapper-spring ${project.version} compile tk.mybatis mapper-weekend ${project.version} compile tk.mybatis mapper-generator ${project.version} compile org.codehaus.mojo flatten-maven-plugin 1.6.0 true bom flatten process-resources flatten flatten.clean clean clean ================================================ FILE: base/README.md ================================================ # Mybatis 通用 Mapper 基础方法实现 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-base/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-base) ================================================ FILE: base/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-base jar mapper-base Mybatis 通用 Mapper 基础方法实现 https://mybatis.io jakarta.persistence jakarta.persistence-api tk.mybatis mapper-core ${project.version} true org.mybatis mybatis com.mysql mysql-connector-j 8.0.33 test ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/BaseMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.base.BaseDeleteMapper; import tk.mybatis.mapper.common.base.BaseInsertMapper; import tk.mybatis.mapper.common.base.BaseSelectMapper; import tk.mybatis.mapper.common.base.BaseUpdateMapper; /** * 通用Mapper接口,其他接口继承该接口即可 *

*

这是一个例子,自己扩展时可以参考

*

*

项目地址 : https://github.com/abel533/Mapper

* * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface BaseMapper extends BaseSelectMapper, BaseInsertMapper, BaseUpdateMapper, BaseDeleteMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/ConditionMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.condition.*; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface ConditionMapper extends SelectByConditionMapper, SelectCountByConditionMapper, DeleteByConditionMapper, UpdateByConditionMapper, UpdateByConditionSelectiveMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/ExampleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.example.*; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface ExampleMapper extends SelectByExampleMapper, SelectOneByExampleMapper, SelectCountByExampleMapper, DeleteByExampleMapper, UpdateByExampleMapper, UpdateByExampleSelectiveMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/IdsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.ids.DeleteByIdsMapper; import tk.mybatis.mapper.common.ids.SelectByIdsMapper; /** * 通用Mapper接口,根据ids操作 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface IdsMapper extends SelectByIdsMapper, DeleteByIdsMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/Mapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; /** * 通用Mapper接口,其他接口继承该接口即可 *

*

这是一个例子,自己扩展时可以参考

*

*

项目地址 : https://github.com/abel533/Mapper

* * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface Mapper extends BaseMapper, ExampleMapper, RowBoundsMapper, SaveMapper, Marker { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/Marker.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; /** * 标记接口,继承该接口的接口,在MapperScannerConfigurer#setMarkerInterface时,会自动注册到通用Mapper * * @author liuzh * @since 3.2.2 */ public interface Marker { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/MySqlMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.special.InsertListMapper; import tk.mybatis.mapper.common.special.InsertUseGeneratedKeysMapper; /** * 通用Mapper接口,MySql独有的通用方法 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface MySqlMapper extends InsertListMapper, InsertUseGeneratedKeysMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/RowBoundsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.rowbounds.SelectByExampleRowBoundsMapper; import tk.mybatis.mapper.common.rowbounds.SelectRowBoundsMapper; /** * 通用Mapper接口,带RowBounds参数的查询 *

* 配合分页插件PageHelper可以实现物理分页 *

* PageHelper - http://git.oschina.net/free/Mybatis_PageHelper * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface RowBoundsMapper extends SelectByExampleRowBoundsMapper, SelectRowBoundsMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/SaveMapper.java ================================================ package tk.mybatis.mapper.common; import org.apache.ibatis.annotations.InsertProvider; import tk.mybatis.mapper.provider.SaveProvider; /** * 通用Mapper接口,保存 *

判断主键是否存在, 如果存在且不为空执行update语句,如果主键不存在或为空, 执行insert语句

* Created by YangBin on 2020/5/12 * Copyright (c) 2020 杨斌 All rights reserved. */ public interface SaveMapper { /** * 保存一个实体,如果实体的主键不为null则更新记录, 主键不存在或主键为null, 则插入记录 * * @param record 不能为空 * @return */ @InsertProvider(type = SaveProvider.class, method = "dynamicSQL") int save(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/SqlServerMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common; import tk.mybatis.mapper.common.sqlserver.InsertMapper; import tk.mybatis.mapper.common.sqlserver.InsertSelectiveMapper; /** * 通用Mapper接口,SqlServerMapper独有的通用方法 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SqlServerMapper extends InsertMapper, InsertSelectiveMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/BaseDeleteMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.common.base.delete.DeleteByPrimaryKeyMapper; import tk.mybatis.mapper.common.base.delete.DeleteMapper; /** * 通用Mapper接口,基础删除 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface BaseDeleteMapper extends DeleteMapper, DeleteByPrimaryKeyMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/BaseInsertMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.common.base.insert.InsertMapper; import tk.mybatis.mapper.common.base.insert.InsertSelectiveMapper; /** * 通用Mapper接口,基础查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface BaseInsertMapper extends InsertMapper, InsertSelectiveMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/BaseSelectMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.common.base.select.*; /** * 通用Mapper接口,基础查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface BaseSelectMapper extends SelectOneMapper, SelectMapper, SelectAllMapper, SelectCountMapper, SelectByPrimaryKeyMapper, ExistsWithPrimaryKeyMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/BaseUpdateMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeyMapper; import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeySelectiveMapper; /** * 通用Mapper接口,基础查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface BaseUpdateMapper extends UpdateByPrimaryKeyMapper, UpdateByPrimaryKeySelectiveMapper { } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/delete/DeleteByPrimaryKeyMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.delete; import org.apache.ibatis.annotations.DeleteProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseDeleteProvider; /** * 通用Mapper接口,删除 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface DeleteByPrimaryKeyMapper { /** * 根据主键字段进行删除,方法参数必须包含完整的主键属性 * * @param key * @return */ @DeleteProvider(type = BaseDeleteProvider.class, method = "dynamicSQL") int deleteByPrimaryKey(Object key); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/delete/DeleteMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.delete; import org.apache.ibatis.annotations.DeleteProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseDeleteProvider; /** * 通用Mapper接口,删除 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface DeleteMapper { /** * 根据实体属性作为条件进行删除,查询条件使用等号 * * @param record * @return */ @DeleteProvider(type = BaseDeleteProvider.class, method = "dynamicSQL") int delete(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/insert/InsertMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.insert; import org.apache.ibatis.annotations.InsertProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseInsertProvider; /** * 通用Mapper接口,插入 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface InsertMapper { /** * 保存一个实体,null的属性也会保存,不会使用数据库默认值 * * @param record * @return */ @InsertProvider(type = BaseInsertProvider.class, method = "dynamicSQL") int insert(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/insert/InsertSelectiveMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.insert; import org.apache.ibatis.annotations.InsertProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseInsertProvider; /** * 通用Mapper接口,插入 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface InsertSelectiveMapper { /** * 保存一个实体,null的属性不会保存,会使用数据库默认值 * * @param record * @return */ @InsertProvider(type = BaseInsertProvider.class, method = "dynamicSQL") int insertSelective(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/select/ExistsWithPrimaryKeyMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.select; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseSelectProvider; /** * 通用Mapper接口,查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface ExistsWithPrimaryKeyMapper { /** * 根据主键字段查询总数,方法参数必须包含完整的主键属性,查询条件使用等号 * * @param key * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") boolean existsWithPrimaryKey(Object key); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/select/SelectAllMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.select; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseSelectProvider; import java.util.List; /** * @author liuzh */ @RegisterMapper public interface SelectAllMapper { /** * 查询全部结果 * * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") List selectAll(); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/select/SelectByPrimaryKeyMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.select; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseSelectProvider; /** * 通用Mapper接口,其他接口继承该接口即可 * 需要在Entity类中为主键字段加上@javax.persistence.Id注解,声明主键 * 否则无法确认实体类哪个属性是主键 *

*

这是一个例子,自己扩展时可以参考

*

*

项目地址 : https://github.com/abel533/Mapper

* * @param 不能为空 * @author liuzh */ @RegisterMapper public interface SelectByPrimaryKeyMapper { /** * 根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号 * * @param key * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") T selectByPrimaryKey(Object key); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/select/SelectCountMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.select; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseSelectProvider; /** * 通用Mapper接口,查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface SelectCountMapper { /** * 根据实体中的属性查询总数,查询条件使用等号 * * @param record * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") int selectCount(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/select/SelectMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.select; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseSelectProvider; import java.util.List; /** * 通用Mapper接口,查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface SelectMapper { /** * 根据实体中的属性值进行查询,查询条件使用等号 * * @param record * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") List select(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/select/SelectOneMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.select; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseSelectProvider; /** * 通用Mapper接口,查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface SelectOneMapper { /** * 根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号 * * @param record * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") T selectOne(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/update/UpdateByPrimaryKeyMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.update; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseUpdateProvider; /** * 通用Mapper接口,更新 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface UpdateByPrimaryKeyMapper { /** * 根据主键更新实体全部字段,null值会被更新 * * @param record * @return */ @UpdateProvider(type = BaseUpdateProvider.class, method = "dynamicSQL") int updateByPrimaryKey(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/base/update/UpdateByPrimaryKeySelectiveMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.base.update; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseUpdateProvider; /** * 通用Mapper接口,更新 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface UpdateByPrimaryKeySelectiveMapper { /** * 根据主键更新属性不为null的值 * * @param record * @return */ @UpdateProvider(type = BaseUpdateProvider.class, method = "dynamicSQL") int updateByPrimaryKeySelective(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/condition/DeleteByConditionMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.condition; import org.apache.ibatis.annotations.DeleteProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.ConditionProvider; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @RegisterMapper public interface DeleteByConditionMapper { /** * 根据Condition条件删除数据 * * @param condition * @return */ @DeleteProvider(type = ConditionProvider.class, method = "dynamicSQL") int deleteByCondition(Object condition); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/condition/SelectByConditionMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.condition; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.provider.ConditionProvider; import java.util.List; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectByConditionMapper { /** * 根据Condition条件进行查询 * * @param condition * @return */ @SelectProvider(type = ConditionProvider.class, method = "dynamicSQL") List selectByCondition(Object condition); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/condition/SelectCountByConditionMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.condition; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.provider.ConditionProvider; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectCountByConditionMapper { /** * 根据Condition条件进行查询总数 * * @param condition * @return */ @SelectProvider(type = ConditionProvider.class, method = "dynamicSQL") int selectCountByCondition(Object condition); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/condition/UpdateByConditionMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.condition; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.provider.ConditionProvider; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface UpdateByConditionMapper { /** * 根据Condition条件更新实体`record`包含的全部属性,null值会被更新 * * @param record * @param condition * @return */ @UpdateProvider(type = ConditionProvider.class, method = "dynamicSQL") int updateByCondition(@Param("record") T record, @Param("example") Object condition); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/condition/UpdateByConditionSelectiveMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.condition; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.provider.ConditionProvider; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface UpdateByConditionSelectiveMapper { /** * 根据Condition条件更新实体`record`包含的不是null的属性值 * * @param record * @param condition * @return */ @UpdateProvider(type = ConditionProvider.class, method = "dynamicSQL") int updateByConditionSelective(@Param("record") T record, @Param("example") Object condition); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/example/DeleteByExampleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.example; import org.apache.ibatis.annotations.DeleteProvider; import tk.mybatis.mapper.provider.ExampleProvider; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface DeleteByExampleMapper { /** * 根据Example条件删除数据 * * @param example * @return */ @DeleteProvider(type = ExampleProvider.class, method = "dynamicSQL") int deleteByExample(Object example); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/example/SelectByExampleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.example; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.provider.ExampleProvider; import java.util.List; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectByExampleMapper { /** * 根据Example条件进行查询 * * @param example * @return */ @SelectProvider(type = ExampleProvider.class, method = "dynamicSQL") List selectByExample(Object example); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/example/SelectCountByExampleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.example; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.provider.ExampleProvider; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectCountByExampleMapper { /** * 根据Example条件进行查询总数 * * @param example * @return */ @SelectProvider(type = ExampleProvider.class, method = "dynamicSQL") int selectCountByExample(Object example); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/example/SelectOneByExampleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.example; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.provider.ExampleProvider; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectOneByExampleMapper { /** * 根据Example条件进行查询 * * @param example * @return */ @SelectProvider(type = ExampleProvider.class, method = "dynamicSQL") T selectOneByExample(Object example); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/example/UpdateByExampleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.example; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.provider.ExampleProvider; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface UpdateByExampleMapper { /** * 根据Example条件更新实体`record`包含的全部属性,null值会被更新 * * @param record * @param example * @return */ @UpdateProvider(type = ExampleProvider.class, method = "dynamicSQL") int updateByExample(@Param("record") T record, @Param("example") Object example); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/example/UpdateByExampleSelectiveMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.example; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.provider.ExampleProvider; /** * 通用Mapper接口,Example查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface UpdateByExampleSelectiveMapper { /** * 根据Example条件更新实体`record`包含的不是null的属性值 * * @param record * @param example * @return */ @UpdateProvider(type = ExampleProvider.class, method = "dynamicSQL") int updateByExampleSelective(@Param("record") T record, @Param("example") Object example); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/ids/DeleteByIdsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.ids; import org.apache.ibatis.annotations.DeleteProvider; import tk.mybatis.mapper.provider.IdsProvider; /** * 通用Mapper接口,根据ids删除 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface DeleteByIdsMapper { /** * 根据主键字符串进行删除,类中只有存在一个带有@Id注解的字段 * * @param ids 如 "1,2,3,4" * @return */ @DeleteProvider(type = IdsProvider.class, method = "dynamicSQL") int deleteByIds(String ids); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/ids/SelectByIdsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.ids; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.provider.IdsProvider; import java.util.List; /** * 通用Mapper接口,根据ids查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectByIdsMapper { /** * 根据主键字符串进行查询,类中只有存在一个带有@Id注解的字段 * * @param ids 如 "1,2,3,4" * @return */ @SelectProvider(type = IdsProvider.class, method = "dynamicSQL") List selectByIds(String ids); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/progressive/ProgressiveMapper.java ================================================ package tk.mybatis.mapper.common.progressive; import org.apache.ibatis.session.RowBounds; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.common.ExampleMapper; import tk.mybatis.mapper.common.rowbounds.SelectByExampleRowBoundsMapper; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.util.Assert; import tk.mybatis.mapper.util.Sqls; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.function.Consumer; /** * 渐进式处理Mapper,数据库必须包含id字段 * @author 陈添明 */ @RegisterMapper public interface ProgressiveMapper extends ExampleMapper, SelectByExampleRowBoundsMapper { /** * 渐进式记录处理 * 数据表必须包含id字段 * @param consumer 业务处理逻辑 * @throws NoSuchFieldException 没有id字段会抛出此异常 * @throws IllegalAccessException 无法访问id字段会抛出此异常 */ default void handleRecordProgressive(Consumer consumer) throws NoSuchFieldException, IllegalAccessException { Class clz = getParameterType(); long i = 0; while (true) { Example example = Example.builder(clz) .andWhere(Sqls.custom().andGreaterThan("id", i)) .build(); List list = selectByExampleAndRowBounds(example, new RowBounds(0, 100)); if (list.isEmpty()) { return; } for (T t : list) { consumer.accept(t); } T t = list.get(list.size() - 1); Field idField = t.getClass().getDeclaredField("id"); idField.setAccessible(true); i = (Long) idField.get(t); } } /** * 渐进式全量删除 * 数据表必须包含id字段 * 不会因为数据量大导致慢sql * @throws NoSuchFieldException 没有id字段会抛出此异常 * @throws IllegalAccessException 无法访问id字段会抛出此异常 */ default void deleteAllProgressive() throws NoSuchFieldException, IllegalAccessException { Class parameterType = getParameterType(); Long minimumId = getMinimumId(); if (minimumId == null) { return; } Long maxId = getMaxId(); if (maxId == null) { return; } for (Long i = minimumId; i <= maxId; ) { i = i + 10000; Example example = Example.builder(parameterType) .andWhere(Sqls.custom().andBetween("id", minimumId, i)) .build(); deleteByExample(example); } } /** * 获取泛型参数Class * * @return 泛型参数Class */ default Class getParameterType() { Type[] genericInterfaces = this.getClass().getGenericInterfaces(); Class rawClass = (Class) genericInterfaces[0]; Type[] rawClassGenericInterfaces = rawClass.getGenericInterfaces(); Assert.isTrue(rawClassGenericInterfaces.length > 0, "Mapper类必须继承泛型Mapper"); ParameterizedType mapperType = getParameterizedType(rawClassGenericInterfaces); Assert.notNull(mapperType, "未找到参数化Mapper类型!"); return (Class) mapperType.getActualTypeArguments()[0]; } /** * 获取ParameterizedType * @param rawClassGenericInterfaces 参数化接口 * @return ParameterizedType */ default ParameterizedType getParameterizedType(Type[] rawClassGenericInterfaces) { for (Type genericInterface : rawClassGenericInterfaces) { if (genericInterface instanceof ParameterizedType) { return (ParameterizedType) genericInterface; } } return null; } /** * 获取最小id * @return 最小id * @throws NoSuchFieldException 没有id字段会抛出此异常 * @throws IllegalAccessException 无法访问id字段会抛出此异常 */ default Long getMinimumId() throws NoSuchFieldException, IllegalAccessException { Class parameterType = getParameterType(); Example example = Example.builder(parameterType) .select("id") .orderBy("id") .build(); List list = selectByExampleAndRowBounds(example, new RowBounds(0, 1)); if (list.isEmpty()) { return null; } T t = list.get(0); Field idField = t.getClass().getDeclaredField("id"); idField.setAccessible(true); return (Long) idField.get(t); } /** * 获取最大id * @return 最大id * @throws NoSuchFieldException 没有id字段会抛出此异常 * @throws IllegalAccessException 无法访问id字段会抛出此异常 */ default Long getMaxId() throws NoSuchFieldException, IllegalAccessException { Class parameterType = getParameterType(); Example example = Example.builder(parameterType) .select("id") .orderByDesc("id") .build(); List list = selectByExampleAndRowBounds(example, new RowBounds(0, 1)); if (list.isEmpty()) { return null; } T t = list.get(0); Field idField = t.getClass().getDeclaredField("id"); idField.setAccessible(true); return (Long) idField.get(t); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/rowbounds/SelectByConditionRowBoundsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.rowbounds; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.session.RowBounds; import tk.mybatis.mapper.provider.ConditionProvider; import java.util.List; /** * 通用Mapper接口,Condition查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectByConditionRowBoundsMapper { /** * 根据example条件和RowBounds进行分页查询,该方法和selectByExampleAndRowBounds完全一样,只是名字改成了Condition * * @param condition * @param rowBounds * @return */ @SelectProvider(type = ConditionProvider.class, method = "dynamicSQL") List selectByConditionAndRowBounds(Object condition, RowBounds rowBounds); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/rowbounds/SelectByExampleRowBoundsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.rowbounds; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.session.RowBounds; import tk.mybatis.mapper.provider.ExampleProvider; import java.util.List; /** * 通用Mapper接口,查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectByExampleRowBoundsMapper { /** * 根据example条件和RowBounds进行分页查询 * * @param example * @param rowBounds * @return */ @SelectProvider(type = ExampleProvider.class, method = "dynamicSQL") List selectByExampleAndRowBounds(Object example, RowBounds rowBounds); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/rowbounds/SelectRowBoundsMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.rowbounds; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.session.RowBounds; import tk.mybatis.mapper.provider.base.BaseSelectProvider; import java.util.List; /** * 通用Mapper接口,查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectRowBoundsMapper { /** * 根据实体属性和RowBounds进行分页查询 * * @param record * @param rowBounds * @return */ @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") List selectByRowBounds(T record, RowBounds rowBounds); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/special/InsertListMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.special; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.Options; import tk.mybatis.mapper.provider.SpecialProvider; import java.util.List; /** * 通用Mapper接口,特殊方法,批量插入,支持批量插入的数据库都可以使用,例如mysql,h2等 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface InsertListMapper { /** * 批量插入,支持批量插入的数据库可以使用,例如MySQL,H2等,另外该接口限制实体包含`id`属性并且必须为自增列 * * @param recordList * @return */ @Options(useGeneratedKeys = true) @InsertProvider(type = SpecialProvider.class, method = "dynamicSQL") int insertList(List recordList); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/special/InsertUseGeneratedKeysMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.special; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.Options; import tk.mybatis.mapper.provider.SpecialProvider; /** * 通用Mapper接口,特殊方法,批量插入,支持批量插入的数据库都可以使用,例如mysql,h2等 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface InsertUseGeneratedKeysMapper { /** * 插入数据,限制为实体包含`id`属性并且必须为自增列,实体配置的主键策略无效 * * @param record * @return */ @Options(useGeneratedKeys = true) @InsertProvider(type = SpecialProvider.class, method = "dynamicSQL") int insertUseGeneratedKeys(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/sqlserver/InsertMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.sqlserver; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.Options; import tk.mybatis.mapper.provider.SqlServerProvider; /** * 通用Mapper接口,插入 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface InsertMapper { /** * 插入数据库,`null`值也会插入,不会使用列的默认值 * * @param record * @return */ @Options(useGeneratedKeys = true) @InsertProvider(type = SqlServerProvider.class, method = "dynamicSQL") int insert(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/common/sqlserver/InsertSelectiveMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.common.sqlserver; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.Options; import tk.mybatis.mapper.provider.SqlServerProvider; /** * 通用Mapper接口,插入 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface InsertSelectiveMapper { @Options(useGeneratedKeys = true) @InsertProvider(type = SqlServerProvider.class, method = "dynamicSQL") int insertSelective(T record); } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/ConditionProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; /** * ConditionProvider实现类,基础方法实现类 * * @author liuzh */ public class ConditionProvider extends MapperTemplate { private ExampleProvider exampleProvider; public ConditionProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); exampleProvider = new ExampleProvider(mapperClass, mapperHelper); } /** * 根据Condition查询总数 * * @param ms * @return */ public String selectCountByCondition(MappedStatement ms) { return exampleProvider.selectCountByExample(ms); } /** * 根据Condition删除 * * @param ms * @return */ public String deleteByCondition(MappedStatement ms) { return exampleProvider.deleteByExample(ms); } /** * 根据Condition查询 * * @param ms * @return */ public String selectByCondition(MappedStatement ms) { return exampleProvider.selectByExample(ms); } /** * 根据Condition查询 * * @param ms * @return */ public String selectByConditionAndRowBounds(MappedStatement ms) { return exampleProvider.selectByExample(ms); } /** * 根据Example更新非null字段 * * @param ms * @return */ public String updateByConditionSelective(MappedStatement ms) { return exampleProvider.updateByExampleSelective(ms); } /** * 根据Condition更新 * * @param ms * @return */ public String updateByCondition(MappedStatement ms) { return exampleProvider.updateByExample(ms); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/ExampleProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.util.MetaObjectUtil; /** * ExampleProvider实现类,基础方法实现类 * * @author liuzh */ public class ExampleProvider extends MapperTemplate { public ExampleProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 根据Example查询总数 * * @param ms * @return */ public String selectCountByExample(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder("SELECT "); if (isCheckExampleEntityClass()) { sql.append(SqlHelper.exampleCheck(entityClass)); } sql.append(SqlHelper.exampleCountColumn(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.exampleWhereClause()); sql.append(SqlHelper.exampleForUpdate()); return sql.toString(); } /** * 根据Example删除 * * @param ms * @return */ public String deleteByExample(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); if (isCheckExampleEntityClass()) { sql.append(SqlHelper.exampleCheck(entityClass)); } //如果设置了安全删除,就不允许执行不带查询条件的 delete 方法 if (getConfig().isSafeDelete()) { sql.append(SqlHelper.exampleHasAtLeastOneCriteriaCheck("_parameter")); } if (SqlHelper.hasLogicDeleteColumn(entityClass)) { sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(""); sql.append(SqlHelper.logicDeleteColumnEqualsValue(entityClass, true)); sql.append(""); MetaObjectUtil.forObject(ms).setValue("sqlCommandType", SqlCommandType.UPDATE); } else { sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); } sql.append(SqlHelper.exampleWhereClause()); return sql.toString(); } /** * 根据Example查询 * * @param ms * @return */ public String selectByExample(MappedStatement ms) { Class entityClass = getEntityClass(ms); //将返回值修改为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder("SELECT "); if (isCheckExampleEntityClass()) { sql.append(SqlHelper.exampleCheck(entityClass)); } sql.append("distinct"); //支持查询指定列 sql.append(SqlHelper.exampleSelectColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.exampleWhereClause()); sql.append(SqlHelper.exampleOrderBy(entityClass)); sql.append(SqlHelper.exampleForUpdate()); return sql.toString(); } /** * 根据Example查询 * * @param ms * @return */ public String selectByExampleAndRowBounds(MappedStatement ms) { return selectByExample(ms); } /** * 根据Example更新非null字段 * * @param ms * @return */ public String updateByExampleSelective(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); if (isCheckExampleEntityClass()) { sql.append(SqlHelper.exampleCheck(entityClass)); } //安全更新,Example 必须包含条件 if (getConfig().isSafeUpdate()) { sql.append(SqlHelper.exampleHasAtLeastOneCriteriaCheck("example")); } sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass), "example")); sql.append(SqlHelper.updateSetColumnsIgnoreVersion(entityClass, "record", true, isNotEmpty())); sql.append(SqlHelper.updateByExampleWhereClause()); return sql.toString(); } /** * 根据Example更新 * * @param ms * @return */ public String updateByExample(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); if (isCheckExampleEntityClass()) { sql.append(SqlHelper.exampleCheck(entityClass)); } //安全更新,Example 必须包含条件 if (getConfig().isSafeUpdate()) { sql.append(SqlHelper.exampleHasAtLeastOneCriteriaCheck("example")); } sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass), "example")); sql.append(SqlHelper.updateSetColumnsIgnoreVersion(entityClass, "record", false, false)); sql.append(SqlHelper.updateByExampleWhereClause()); return sql.toString(); } /** * 根据Example查询一个结果 * * @param ms * @return */ public String selectOneByExample(MappedStatement ms) { return selectByExample(ms); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/IdsProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Set; /** * 通过 ids 字符串的各种操作 *

* ids 如 "1,2,3" * * @author liuzh */ public class IdsProvider extends MapperTemplate { public IdsProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 根据主键字符串进行删除,类中只有存在一个带有@Id注解的字段 * * @param ms * @return */ public String deleteByIds(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); Set columnList = EntityHelper.getPKColumns(entityClass); if (columnList.size() == 1) { EntityColumn column = columnList.iterator().next(); sql.append(" where "); sql.append(column.getColumn()); sql.append(" in (${_parameter})"); } else { throw new MapperException("继承 deleteByIds 方法的实体类[" + entityClass.getName() + "]中必须只有一个带有 @Id 注解的字段"); } return sql.toString(); } /** * 根据主键字符串进行查询,类中只有存在一个带有@Id注解的字段 * * @param ms * @return */ public String selectByIds(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //将返回值修改为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); Set columnList = EntityHelper.getPKColumns(entityClass); if (columnList.size() == 1) { EntityColumn column = columnList.iterator().next(); sql.append(" where "); sql.append(column.getColumn()); sql.append(" in (${_parameter})"); } else { throw new MapperException("继承 selectByIds 方法的实体类[" + entityClass.getName() + "]中必须只有一个带有 @Id 注解的字段"); } return sql.toString(); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/SaveProvider.java ================================================ package tk.mybatis.mapper.provider; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.*; import java.lang.reflect.Field; import java.util.Set; /** * 保存实现类 * Created by YangBin on 2020/5/12 * Copyright (c) 2020 杨斌 All rights reserved. */ public class SaveProvider extends MapperTemplate { public SaveProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 保存策略: 如果主键不为空则更新记录, 如果没有主键或者主键为空,则插入. * @param ms * @return */ public String save(MappedStatement ms){ Class entityClass = getEntityClass(ms); Field[] fields = entityClass.getFields(); StringBuilder sql = new StringBuilder(); Set columnList = EntityHelper.getPKColumns(entityClass); if (columnList.size() == 1) { EntityColumn column = (EntityColumn)columnList.iterator().next(); String id = column.getColumn(); sql.append(""); sql.append(""); sql.append(updateByPrimaryKey(ms)); sql.append(""); sql.append(""); sql.append(insert(ms)); sql.append(""); sql.append(""); return sql.toString(); } return insert(ms); } /** * 通过主键更新全部字段 * * @param ms */ public String updateByPrimaryKey(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.updateSetColumns(entityClass, null, false, false)); sql.append(SqlHelper.wherePKColumns(entityClass, true)); return sql.toString(); } public String insert(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); //获取全部列 Set columnList = EntityHelper.getColumns(entityClass); processKey(sql, entityClass, ms, columnList); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.insertColumns(entityClass, false, false, false)); sql.append(""); for (EntityColumn column : columnList) { if (!column.isInsertable()) { continue; } //优先使用传入的属性值,当原属性property!=null时,用原属性 //自增的情况下,如果默认有值,就会备份到property_cache中,所以这里需要先判断备份的值是否存在 if (column.isIdentity()) { sql.append(SqlHelper.getIfCacheNotNull(column, column.getColumnHolder(null, "_cache", ","))); } else { //其他情况值仍然存在原property中 sql.append(SqlHelper.getIfNotNull(column, column.getColumnHolder(null, null, ","), isNotEmpty())); } //当属性为null时,如果存在主键策略,会自动获取值,如果不存在,则使用null if (column.isIdentity()) { sql.append(SqlHelper.getIfCacheIsNull(column, column.getColumnHolder() + ",")); } else { //当null的时候,如果不指定jdbcType,oracle可能会报异常,指定VARCHAR不影响其他 sql.append(SqlHelper.getIfIsNull(column, column.getColumnHolder(null, null, ","), isNotEmpty())); } } sql.append(""); return sql.toString(); } private void processKey(StringBuilder sql, Class entityClass, MappedStatement ms, Set columnList){ //Identity列只能有一个 Boolean hasIdentityKey = false; //先处理cache或bind节点 for (EntityColumn column : columnList) { if (column.isIdentity()) { //这种情况下,如果原先的字段有值,需要先缓存起来,否则就一定会使用自动增长 //这是一个bind节点 sql.append(SqlHelper.getBindCache(column)); //如果是Identity列,就需要插入selectKey //如果已经存在Identity列,抛出异常 if (hasIdentityKey) { //jdbc类型只需要添加一次 if (column.getGenerator() != null && column.getGenerator().equals("JDBC")) { continue; } throw new MapperException(ms.getId() + "对应的实体类" + entityClass.getName() + "中包含多个MySql的自动增长列,最多只能有一个!"); } //插入selectKey SelectKeyHelper.newSelectKeyMappedStatement(ms, column, entityClass, isBEFORE(), getIDENTITY(column)); hasIdentityKey = true; } else if(column.getGenIdClass() != null){ sql.append(""); } } } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/SpecialProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Set; /** * SpecialProvider实现类,特殊方法实现类 * * @author liuzh */ public class SpecialProvider extends MapperTemplate { public SpecialProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 批量插入 * * @param ms */ public String insertList(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //开始拼sql StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass), "list[0]")); sql.append(SqlHelper.insertColumns(entityClass, true, false, false)); sql.append(" VALUES "); sql.append(""); sql.append(""); //获取全部列 Set columnList = EntityHelper.getColumns(entityClass); //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnList) { if (!column.isId() && column.isInsertable()) { sql.append(column.getColumnHolder("record") + ","); } } sql.append(""); sql.append(""); // 反射把MappedStatement中的设置主键名 EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } /** * 插入,主键id,自增 * * @param ms */ public String insertUseGeneratedKeys(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //开始拼sql StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.insertColumns(entityClass, true, false, false)); sql.append(SqlHelper.insertValuesColumns(entityClass, true, false, false)); // 反射把MappedStatement中的设置主键名 EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/SqlServerProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; /** * SqlServerProvider实现类,特殊方法实现类 * * @author liuzh */ public class SqlServerProvider extends MapperTemplate { public SqlServerProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 插入 * * @param ms */ public String insert(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //开始拼sql StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.insertColumns(entityClass, true, false, false)); sql.append(SqlHelper.insertValuesColumns(entityClass, true, false, false)); // 反射把MappedStatement中的设置主键名 EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } /** * 插入不为null的字段 * * @param ms * @return */ public String insertSelective(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.insertColumns(entityClass, true, true, isNotEmpty())); sql.append(SqlHelper.insertValuesColumns(entityClass, true, true, isNotEmpty())); // 反射把MappedStatement中的设置主键名 EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/base/BaseDeleteProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider.base; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.util.MetaObjectUtil; /** * BaseDeleteMapper实现类,基础方法实现类 * * @author liuzh */ public class BaseDeleteProvider extends MapperTemplate { public BaseDeleteProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 通过条件删除 * * @param ms * @return */ public String delete(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); //如果设置了安全删除,就不允许执行不带查询条件的 delete 方法 if (getConfig().isSafeDelete()) { sql.append(SqlHelper.notAllNullParameterCheck("_parameter", EntityHelper.getColumns(entityClass))); } // 如果是逻辑删除,则修改为更新表,修改逻辑删除字段的值 if (SqlHelper.hasLogicDeleteColumn(entityClass)) { sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(""); sql.append(SqlHelper.logicDeleteColumnEqualsValue(entityClass, true)); sql.append(""); MetaObjectUtil.forObject(ms).setValue("sqlCommandType", SqlCommandType.UPDATE); } else { sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); } sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty())); return sql.toString(); } /** * 通过主键删除 * * @param ms */ public String deleteByPrimaryKey(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); if (SqlHelper.hasLogicDeleteColumn(entityClass)) { sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(""); sql.append(SqlHelper.logicDeleteColumnEqualsValue(entityClass, true)); sql.append(""); MetaObjectUtil.forObject(ms).setValue("sqlCommandType", SqlCommandType.UPDATE); } else { sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); } sql.append(SqlHelper.wherePKColumns(entityClass)); return sql.toString(); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/base/BaseInsertProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider.base; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.*; import java.util.Set; /** * BaseInsertProvider实现类,基础方法实现类 * * @author liuzh */ public class BaseInsertProvider extends MapperTemplate { public BaseInsertProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String insert(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); //获取全部列 Set columnList = EntityHelper.getColumns(entityClass); EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); processKey(sql, entityClass, ms, columnList); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.insertColumns(entityClass, false, false, false)); sql.append(""); for (EntityColumn column : columnList) { if (!column.isInsertable()) { continue; } if (logicDeleteColumn != null && logicDeleteColumn == column) { sql.append(SqlHelper.getLogicDeletedValue(column, false)).append(","); continue; } //优先使用传入的属性值,当原属性property!=null时,用原属性 //自增的情况下,如果默认有值,就会备份到property_cache中,所以这里需要先判断备份的值是否存在 if (column.isIdentity()) { sql.append(SqlHelper.getIfCacheNotNull(column, column.getColumnHolder(null, "_cache", ","))); } else { //其他情况值仍然存在原property中 sql.append(SqlHelper.getIfNotNull(column, column.getColumnHolder(null, null, ","), isNotEmpty())); } //当属性为null时,如果存在主键策略,会自动获取值,如果不存在,则使用null if (column.isIdentity()) { sql.append(SqlHelper.getIfCacheIsNull(column, column.getColumnHolder() + ",")); } else { //当null的时候,如果不指定jdbcType,oracle可能会报异常,指定VARCHAR不影响其他 sql.append(SqlHelper.getIfIsNull(column, column.getColumnHolder(null, null, ","), isNotEmpty())); } } sql.append(""); return sql.toString(); } public String insertSelective(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); //获取全部列 Set columnList = EntityHelper.getColumns(entityClass); EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); processKey(sql, entityClass, ms, columnList); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass))); sql.append(""); for (EntityColumn column : columnList) { if (!column.isInsertable()) { continue; } if (column.isIdentity()) { sql.append(column.getColumn()).append(","); } else { if (logicDeleteColumn != null && logicDeleteColumn == column) { sql.append(column.getColumn()).append(","); continue; } sql.append(SqlHelper.getIfNotNull(column, column.getColumn() + ",", isNotEmpty())); } } sql.append(""); sql.append(""); for (EntityColumn column : columnList) { if (!column.isInsertable()) { continue; } if (logicDeleteColumn != null && logicDeleteColumn == column) { sql.append(SqlHelper.getLogicDeletedValue(column, false)).append(","); continue; } //优先使用传入的属性值,当原属性property!=null时,用原属性 //自增的情况下,如果默认有值,就会备份到property_cache中,所以这里需要先判断备份的值是否存在 if (column.isIdentity()) { sql.append(SqlHelper.getIfCacheNotNull(column, column.getColumnHolder(null, "_cache", ","))); } else { //其他情况值仍然存在原property中 sql.append(SqlHelper.getIfNotNull(column, column.getColumnHolder(null, null, ","), isNotEmpty())); } //当属性为null时,如果存在主键策略,会自动获取值,如果不存在,则使用null //序列的情况 if (column.isIdentity()) { sql.append(SqlHelper.getIfCacheIsNull(column, column.getColumnHolder() + ",")); } } sql.append(""); return sql.toString(); } private void processKey(StringBuilder sql, Class entityClass, MappedStatement ms, Set columnList) { //Identity列只能有一个 Boolean hasIdentityKey = false; //先处理cache或bind节点 for (EntityColumn column : columnList) { if (column.isIdentity()) { //这种情况下,如果原先的字段有值,需要先缓存起来,否则就一定会使用自动增长 //这是一个bind节点 sql.append(SqlHelper.getBindCache(column)); //如果是Identity列,就需要插入selectKey //如果已经存在Identity列,抛出异常 if (hasIdentityKey) { //jdbc类型只需要添加一次 if (column.getGenerator() != null && "JDBC".equals(column.getGenerator())) { continue; } throw new MapperException(ms.getId() + "对应的实体类" + entityClass.getName() + "中包含多个MySql的自动增长列,最多只能有一个!"); } //插入selectKey SelectKeyHelper.newSelectKeyMappedStatement(ms, column, entityClass, isBEFORE(), getIDENTITY(column)); hasIdentityKey = true; } else if (column.getGenIdClass() != null) { sql.append(""); } } } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/base/BaseSelectProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider.base; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; /** * BaseSelectProvider实现类,基础方法实现类 * * @author liuzh */ public class BaseSelectProvider extends MapperTemplate { public BaseSelectProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 查询 * * @param ms * @return */ public String selectOne(MappedStatement ms) { Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty())); return sql.toString(); } /** * 查询 * * @param ms * @return */ public String select(MappedStatement ms) { Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty())); sql.append(SqlHelper.orderByDefault(entityClass)); return sql.toString(); } /** * 查询 * * @param ms * @return */ public String selectByRowBounds(MappedStatement ms) { return select(ms); } /** * 根据主键进行查询 * * @param ms */ public String selectByPrimaryKey(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //将返回值修改为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.wherePKColumns(entityClass)); return sql.toString(); } /** * 查询总数 * * @param ms * @return */ public String selectCount(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectCount(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty())); return sql.toString(); } /** * 根据主键查询总数 * * @param ms * @return */ public String existsWithPrimaryKey(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectCountExists(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.wherePKColumns(entityClass)); return sql.toString(); } /** * 查询全部结果 * * @param ms * @return */ public String selectAll(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); // 逻辑删除的未删除查询条件 sql.append(""); sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); sql.append(SqlHelper.orderByDefault(entityClass)); return sql.toString(); } } ================================================ FILE: base/src/main/java/tk/mybatis/mapper/provider/base/BaseUpdateProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider.base; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; /** * BaseUpdateProvider实现类,基础方法实现类 * * @author liuzh */ public class BaseUpdateProvider extends MapperTemplate { public BaseUpdateProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 通过主键更新全部字段 * * @param ms */ public String updateByPrimaryKey(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.updateSetColumns(entityClass, null, false, false)); sql.append(SqlHelper.wherePKColumns(entityClass, true)); return sql.toString(); } /** * 通过主键更新不为null的字段 * * @param ms * @return */ public String updateByPrimaryKeySelective(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.updateSetColumns(entityClass, null, true, isNotEmpty())); sql.append(SqlHelper.wherePKColumns(entityClass, true)); return sql.toString(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/BaseTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.base; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.sql.Connection; /** * 测试基类 * * @author liuzh */ public abstract class BaseTest { private SqlSessionFactory sqlSessionFactory; @Before public final void init() { try { Reader reader = getConfigFileAsReader(); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); reader.close(); //配置通用 Mapper configMapperHelper(); //执行初始化 SQL runSql(getSqlFileAsReader()); } catch (IOException e) { throw new RuntimeException(e); } } /** * 配置通用 Mapper */ protected void configMapperHelper() { SqlSession session = getSqlSession(); try { //创建一个MapperHelper MapperHelper mapperHelper = new MapperHelper(); //设置配置 mapperHelper.setConfig(getConfig()); //配置完成后,执行下面的操作 mapperHelper.processConfiguration(session.getConfiguration()); } finally { session.close(); } } /** * 执行 Sql * * @param reader */ protected void runSql(Reader reader) { if (reader == null) { return; } SqlSession sqlSession = getSqlSession(); try { Connection conn = sqlSession.getConnection(); ScriptRunner runner = new ScriptRunner(conn); runner.setLogWriter(null); runner.runScript(reader); try { reader.close(); } catch (IOException e) { } } finally { sqlSession.close(); } } /** * 获取 Mapper 配置 * * @return */ protected Config getConfig() { return new Config(); } /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = BaseTest.class.getResource("mybatis-config.xml"); return toReader(url); } ; /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = BaseTest.class.getResource("CreateDB.sql"); return toReader(url); } ; /** * 转为 Reader * * @param url * @return * @throws IOException */ protected Reader toReader(URL url) throws IOException { return Resources.getUrlAsReader(url.toString()); } /** * 获取Session * * @return */ protected SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.base; import jakarta.persistence.Id; import java.io.Serializable; /** * @author liuzh */ public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id private Long id; private String countryname; private String countrycode; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/CountryMapper.java ================================================ package tk.mybatis.mapper.base; import tk.mybatis.mapper.common.Mapper; public interface CountryMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/CreateDB.sql ================================================ drop table country if exists; create table country ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) DEFAULT 'HH', version INTEGER DEFAULT 1 NOT NULL ); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (13, 'Bahamas', 'BS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (14, 'Bahrain', 'BH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (15, 'Bangladesh', 'BD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (16, 'Barbados', 'BB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (17, 'Belarus', 'BY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (18, 'Belgium', 'BE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (19, 'Belize', 'BZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (20, 'Benin', 'BJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (21, 'Bermuda Is.', 'BM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (22, 'Bolivia', 'BO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (23, 'Botswana', 'BW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (24, 'Brazil', 'BR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (25, 'Brunei', 'BN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (26, 'Bulgaria', 'BG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (27, 'Burkina-faso', 'BF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (28, 'Burma', 'MM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (29, 'Burundi', 'BI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (30, 'Cameroon', 'CM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (31, 'Canada', 'CA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (32, 'Central African Republic', 'CF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (33, 'Chad', 'TD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (34, 'Chile', 'CL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (35, 'China', 'CN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (36, 'Colombia', 'CO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (37, 'Congo', 'CG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (38, 'Cook Is.', 'CK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (39, 'Costa Rica', 'CR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (40, 'Cuba', 'CU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (41, 'Cyprus', 'CY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (42, 'Czech Republic', 'CZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (43, 'Denmark', 'DK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (44, 'Djibouti', 'DJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (45, 'Dominica Rep.', 'DO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (46, 'Ecuador', 'EC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (47, 'Egypt', 'EG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (48, 'EI Salvador', 'SV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (49, 'Estonia', 'EE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (50, 'Ethiopia', 'ET', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (51, 'Fiji', 'FJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (52, 'Finland', 'FI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (53, 'France', 'FR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (54, 'French Guiana', 'GF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (55, 'Gabon', 'GA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (56, 'Gambia', 'GM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (57, 'Georgia', 'GE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (58, 'Germany', 'DE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (59, 'Ghana', 'GH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (60, 'Gibraltar', 'GI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (61, 'Greece', 'GR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (62, 'Grenada', 'GD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (63, 'Guam', 'GU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (64, 'Guatemala', 'GT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (65, 'Guinea', 'GN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (66, 'Guyana', 'GY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (67, 'Haiti', 'HT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (68, 'Honduras', 'HN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (69, 'Hongkong', 'HK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (70, 'Hungary', 'HU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (71, 'Iceland', 'IS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (72, 'India', 'IN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (73, 'Indonesia', 'ID', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (74, 'Iran', 'IR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (75, 'Iraq', 'IQ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (76, 'Ireland', 'IE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (77, 'Israel', 'IL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (78, 'Italy', 'IT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (79, 'Jamaica', 'JM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (80, 'Japan', 'JP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (81, 'Jordan', 'JO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (82, 'Kampuchea (Cambodia )', 'KH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (83, 'Kazakstan', 'KZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (84, 'Kenya', 'KE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (85, 'Korea', 'KR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (86, 'Kuwait', 'KW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (87, 'Kyrgyzstan', 'KG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (88, 'Laos', 'LA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (89, 'Latvia', 'LV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (90, 'Lebanon', 'LB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (91, 'Lesotho', 'LS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (92, 'Liberia', 'LR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (93, 'Libya', 'LY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (94, 'Liechtenstein', 'LI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (95, 'Lithuania', 'LT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (96, 'Luxembourg', 'LU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (97, 'Macao', 'MO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (98, 'Madagascar', 'MG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (99, 'Malawi', 'MW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (100, 'Malaysia', 'MY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (101, 'Maldives', 'MV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (102, 'Mali', 'ML', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (103, 'Malta', 'MT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (104, 'Mauritius', 'MU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (105, 'Mexico', 'MX', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (106, 'Moldova, Republic of', 'MD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (107, 'Monaco', 'MC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (108, 'Mongolia', 'MN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (109, 'Montserrat Is', 'MS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (110, 'Morocco', 'MA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (111, 'Mozambique', 'MZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (112, 'Namibia', 'NA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (113, 'Nauru', 'NR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (114, 'Nepal', 'NP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (115, 'Netherlands', 'NL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (116, 'New Zealand', 'NZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (117, 'Nicaragua', 'NI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (118, 'Niger', 'NE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (119, 'Nigeria', 'NG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (120, 'North Korea', 'KP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (121, 'Norway', 'NO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (122, 'Oman', 'OM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (123, 'Pakistan', 'PK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (124, 'Panama', 'PA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (125, 'Papua New Cuinea', 'PG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (126, 'Paraguay', 'PY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (127, 'Peru', 'PE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (128, 'Philippines', 'PH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (129, 'Poland', 'PL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (130, 'French Polynesia', 'PF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (131, 'Portugal', 'PT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (132, 'Puerto Rico', 'PR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (133, 'Qatar', 'QA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (134, 'Romania', 'RO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (135, 'Russia', 'RU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (136, 'Saint Lueia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (137, 'Saint Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (138, 'San Marino', 'SM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (139, 'Sao Tome and Principe', 'ST', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (140, 'Saudi Arabia', 'SA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (141, 'Senegal', 'SN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (142, 'Seychelles', 'SC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (143, 'Sierra Leone', 'SL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (144, 'Singapore', 'SG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (145, 'Slovakia', 'SK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (146, 'Slovenia', 'SI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (147, 'Solomon Is', 'SB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (148, 'Somali', 'SO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (149, 'South Africa', 'ZA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (150, 'Spain', 'ES', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (151, 'Sri Lanka', 'LK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (152, 'St.Lucia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (153, 'St.Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (154, 'Sudan', 'SD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (155, 'Suriname', 'SR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (156, 'Swaziland', 'SZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (157, 'Sweden', 'SE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (158, 'Switzerland', 'CH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (159, 'Syria', 'SY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (160, 'Taiwan', 'TW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (161, 'Tajikstan', 'TJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (162, 'Tanzania', 'TZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (163, 'Thailand', 'TH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (164, 'Togo', 'TG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (165, 'Tonga', 'TO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (166, 'Trinidad and Tobago', 'TT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (167, 'Tunisia', 'TN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (168, 'Turkey', 'TR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (169, 'Turkmenistan', 'TM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (170, 'Uganda', 'UG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (171, 'Ukraine', 'UA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (172, 'United Arab Emirates', 'AE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (173, 'United Kiongdom', 'GB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (174, 'United States of America', 'US', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (175, 'Uruguay', 'UY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (176, 'Uzbekistan', 'UZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (177, 'Venezuela', 'VE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (178, 'Vietnam', 'VN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (179, 'Yemen', 'YE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (180, 'Yugoslavia', 'YU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (181, 'Zimbabwe', 'ZW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (182, 'Zaire', 'ZR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (183, 'Zambia', 'ZM', 1); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/delete/DeleteByPrimaryKeyMapperTest.java ================================================ package tk.mybatis.mapper.base.delete; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.base.CountryMapper; public class DeleteByPrimaryKeyMapperTest extends BaseTest { @Test public void testDeleteByPrimaryKey() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertEquals(183, mapper.selectAll().size()); Assert.assertEquals(1, mapper.deleteByPrimaryKey(1L)); Assert.assertEquals(182, mapper.selectAll().size()); Assert.assertEquals(1, mapper.deleteByPrimaryKey(2)); Assert.assertEquals(181, mapper.selectAll().size()); Assert.assertEquals(1, mapper.deleteByPrimaryKey("3")); Assert.assertEquals(180, mapper.selectAll().size()); Assert.assertEquals(0, mapper.deleteByPrimaryKey(1)); Assert.assertEquals(180, mapper.selectAll().size()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/delete/SafeDeleteByFieldTest.java ================================================ package tk.mybatis.mapper.base.delete; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.base.CountryMapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.Example; public class SafeDeleteByFieldTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setSafeDelete(true); return config; } @Test(expected = PersistenceException.class) public void testSafeDelete() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.delete(new Country()); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.delete(null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteByExample() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.deleteByExample(new Example(Country.class)); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteByExampleNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.deleteByExample(null); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/delete/SafeDeleteByMethodTest.java ================================================ package tk.mybatis.mapper.base.delete; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.base.CountryMapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.Example; public class SafeDeleteByMethodTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setSafeDelete(true); //和 SafeDeleteByFieldTest 测试的区别在此,这里将会使后面调用 EntityField.getValue 时,使用 getter 方法获取值 config.setEnableMethodAnnotation(true); return config; } @Test(expected = PersistenceException.class) public void testSafeDelete() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.delete(new Country()); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.delete(null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteByExample() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.deleteByExample(new Example(Country.class)); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteByExampleNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.deleteByExample(null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeDeleteByExampleWithNullValueCriterion() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andEqualTo("countryname", null); mapper.deleteByExample(example); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.base.genid; import tk.mybatis.mapper.annotation.KeySql; import jakarta.persistence.Id; import java.io.Serializable; /** * @author liuzh */ public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id @KeySql(genId = SimpleGenId.class) private Long id; private String countryname; private String countrycode; public Country() { } public Country(String countryname, String countrycode) { this.countryname = countryname; this.countrycode = countrycode; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/CountryMapper.java ================================================ package tk.mybatis.mapper.base.genid; import tk.mybatis.mapper.common.base.BaseInsertMapper; public interface CountryMapper extends BaseInsertMapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/CreateDB.sql ================================================ drop table country if exists; drop table user if exists; create table country ( id bigint NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) ); create table user ( id varchar(64) NOT NULL PRIMARY KEY, name varchar(32), code VARCHAR(2) ); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/InsertGenIdTest.java ================================================ package tk.mybatis.mapper.base.genid; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import java.io.IOException; import java.io.Reader; import java.net.URL; /** * @author liuzh */ public class InsertGenIdTest extends BaseTest { private String[][] countries = new String[][]{ {"Angola", "AO"}, {"Afghanistan", "AF"}, {"Albania", "AL"}, {"Algeria", "DZ"}, {"Andorra", "AD"}, {"Anguilla", "AI"}, {"Antigua and Barbuda", "AG"}, {"Argentina", "AR"}, {"Armenia", "AM"}, {"Australia", "AU"}, {"Austria", "AT"}, {"Azerbaijan", "AZ"}, {"Bahamas", "BS"}, {"Bahrain", "BH"}, {"Bangladesh", "BD"}, {"Barbados", "BB"}, {"Belarus", "BY"}, {"Belgium", "BE"}, {"Belize", "BZ"}, {"Benin", "BJ"}, {"Bermuda Is.", "BM"}, {"Bolivia", "BO"}, {"Botswana", "BW"}, {"Brazil", "BR"}, {"Brunei", "BN"}, {"Bulgaria", "BG"}, {"Burkina-faso", "BF"}, {"Burma", "MM"}, {"Burundi", "BI"}, {"Cameroon", "CM"}, {"Canada", "CA"}, {"Central African Republic", "CF"}, {"Chad", "TD"}, {"Chile", "CL"}, {"China", "CN"} }; /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } ; /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } ; @Test public void testGenId() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); for (int i = 0; i < countries.length; i++) { Country country = new Country(countries[i][0], countries[i][1]); Assert.assertEquals(1, mapper.insert(country)); Assert.assertNotNull(country.getId()); System.out.println(country.getId()); } } finally { sqlSession.close(); } } @Test public void testGenIdWithExistsId() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country("test", "T"); country.setId(9999L); Assert.assertEquals(1, mapper.insert(country)); Assert.assertNotNull(country.getId()); Assert.assertEquals(new Long(9999), country.getId()); System.out.println(country.getId()); } finally { sqlSession.close(); } } @Test public void testUUID() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); for (int i = 0; i < countries.length; i++) { User user = new User(countries[i][0], countries[i][1]); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); System.out.println(user.getId()); } } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/SimpleGenId.java ================================================ package tk.mybatis.mapper.base.genid; import tk.mybatis.mapper.genid.GenId; /** * 一个简单的实现,不考虑任何特殊情况,不要用于生产环境 * * @author liuzh */ public class SimpleGenId implements GenId { private Long time; private Integer seq; @Override public synchronized Long genId(String table, String column) { long current = System.currentTimeMillis(); if (time == null || time != current) { time = current; seq = 1; } else if (current == time) { seq++; } return (time << 20) | seq; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/UUIdGenId.java ================================================ package tk.mybatis.mapper.base.genid; import tk.mybatis.mapper.genid.GenId; import java.util.UUID; /** * @author liuzh */ public class UUIdGenId implements GenId { @Override public String genId(String table, String column) { return UUID.randomUUID().toString(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/User.java ================================================ package tk.mybatis.mapper.base.genid; import tk.mybatis.mapper.annotation.KeySql; import jakarta.persistence.Id; /** * @author liuzh */ public class User { @Id @KeySql(genId = UUIdGenId.class) private String id; private String name; private String code; public User() { } public User(String name, String code) { this.name = name; this.code = code; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/UserMapper.java ================================================ package tk.mybatis.mapper.base.genid; import tk.mybatis.mapper.common.base.BaseInsertMapper; public interface UserMapper extends BaseInsertMapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/genid/mybatis-config.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/mybatis-config.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/update/SafeUpdateByFieldTest.java ================================================ package tk.mybatis.mapper.base.update; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.base.CountryMapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.Example; public class SafeUpdateByFieldTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setSafeUpdate(true); return config; } @Test(expected = PersistenceException.class) public void testSafeUpdate() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExample(new Country(), new Example(Country.class)); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExample(new Country(), null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateNull2() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExample(null, null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateByExample() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExampleSelective(new Country(), new Example(Country.class)); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateByExampleNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExampleSelective(new Country(), null); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/base/update/SafeUpdateByMethodTest.java ================================================ package tk.mybatis.mapper.base.update; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.base.CountryMapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.Example; public class SafeUpdateByMethodTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setSafeUpdate(true); //和 SafeUpdateByFieldTest 测试的区别在此,这里将会使后面调用 EntityField.getValue 时,使用 getter 方法获取值 config.setEnableMethodAnnotation(true); return config; } @Test(expected = PersistenceException.class) public void testSafeUpdate() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExample(new Country(), new Example(Country.class)); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExample(new Country(), null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateNull2() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExample(null, null); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateByExample() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExampleSelective(new Country(), new Example(Country.class)); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testSafeUpdateByExampleNull() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByExampleSelective(new Country(), null); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/CacheTest.java ================================================ package tk.mybatis.mapper.cache; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.base.CountryMapper; import java.io.IOException; import java.io.Reader; /** * @author liuzh */ public class CacheTest extends BaseTest { @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(CacheTest.class.getResource("mybatis-config-cache.xml")); } @Test public void testNoCache() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); //由于 CountryMapper 没有使用二级缓存,因此下面的设置不会影响下次(不同的 SqlSession)查询 country.setCountryname("中国"); country.setCountrycode("ZH"); } finally { sqlSession.close(); } //下面获取新的 sqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); Assert.assertNotEquals("中国", country.getCountryname()); Assert.assertNotEquals("ZH", country.getCountrycode()); } finally { sqlSession.close(); } } @Test public void testSingleInterfaceCache() { //利用二级缓存的脏数据特性来验证二级缓存 SqlSession sqlSession = getSqlSession(); try { CountryCacheMapper mapper = sqlSession.getMapper(CountryCacheMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); //这里修改会产生脏数据,这么做只是为了验证二级缓存 country.setCountryname("中国"); country.setCountrycode("ZH"); } finally { sqlSession.close(); } //前面 sqlSession.close() 后就会缓存,下面获取新的 sqlSession sqlSession = getSqlSession(); try { CountryCacheMapper mapper = sqlSession.getMapper(CountryCacheMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("中国", country.getCountryname()); Assert.assertEquals("ZH", country.getCountrycode()); } finally { sqlSession.close(); } //下面清空缓存再试 sqlSession = getSqlSession(); try { CountryCacheMapper mapper = sqlSession.getMapper(CountryCacheMapper.class); //调用 update 清空缓存 mapper.updateByPrimaryKey(new Country()); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); } finally { sqlSession.close(); } } @Test public void testCountryCacheRefMapper() { //--------------------selectByPrimaryKey--------------------- //利用二级缓存的脏数据特性来验证二级缓存 SqlSession sqlSession = getSqlSession(); try { CountryCacheRefMapper mapper = sqlSession.getMapper(CountryCacheRefMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); //这里修改会产生脏数据,这么做只是为了验证二级缓存 country.setCountryname("中国"); country.setCountrycode("ZH"); } finally { sqlSession.close(); } //前面 sqlSession.close() 后就会缓存,下面获取新的 sqlSession sqlSession = getSqlSession(); try { CountryCacheRefMapper mapper = sqlSession.getMapper(CountryCacheRefMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("中国", country.getCountryname()); Assert.assertEquals("ZH", country.getCountrycode()); } finally { sqlSession.close(); } //--------------------selectById--------------------- sqlSession = getSqlSession(); try { CountryCacheRefMapper mapper = sqlSession.getMapper(CountryCacheRefMapper.class); Country country = mapper.selectById(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); //这里修改会产生脏数据,这么做只是为了验证二级缓存 country.setCountryname("中国"); country.setCountrycode("ZH"); } finally { sqlSession.close(); } //前面 sqlSession.close() 后就会缓存,下面获取新的 sqlSession sqlSession = getSqlSession(); try { CountryCacheRefMapper mapper = sqlSession.getMapper(CountryCacheRefMapper.class); Country country = mapper.selectById(35); Assert.assertEquals("中国", country.getCountryname()); Assert.assertEquals("ZH", country.getCountrycode()); } finally { sqlSession.close(); } //下面清空缓存再试 sqlSession = getSqlSession(); try { CountryCacheRefMapper mapper = sqlSession.getMapper(CountryCacheRefMapper.class); //调用 update 清空缓存 mapper.updateByPrimaryKey(new Country()); Country country = mapper.selectById(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); } finally { sqlSession.close(); } } @Test @Ignore("MyBatis 有 Bug,这种方式目前行不通") public void testCountryCacheWithXmlMapper() { //--------------------selectByPrimaryKey--------------------- //利用二级缓存的脏数据特性来验证二级缓存 SqlSession sqlSession = getSqlSession(); try { CountryCacheWithXmlMapper mapper = sqlSession.getMapper(CountryCacheWithXmlMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); //这里修改会产生脏数据,这么做只是为了验证二级缓存 country.setCountryname("中国"); country.setCountrycode("ZH"); } finally { sqlSession.close(); } //前面 sqlSession.close() 后就会缓存,下面获取新的 sqlSession sqlSession = getSqlSession(); try { CountryCacheWithXmlMapper mapper = sqlSession.getMapper(CountryCacheWithXmlMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertEquals("中国", country.getCountryname()); Assert.assertEquals("ZH", country.getCountrycode()); } finally { sqlSession.close(); } //--------------------selectById--------------------- sqlSession = getSqlSession(); try { CountryCacheWithXmlMapper mapper = sqlSession.getMapper(CountryCacheWithXmlMapper.class); Country country = mapper.selectById(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); //这里修改会产生脏数据,这么做只是为了验证二级缓存 country.setCountryname("中国"); country.setCountrycode("ZH"); } finally { sqlSession.close(); } //前面 sqlSession.close() 后就会缓存,下面获取新的 sqlSession sqlSession = getSqlSession(); try { CountryCacheWithXmlMapper mapper = sqlSession.getMapper(CountryCacheWithXmlMapper.class); Country country = mapper.selectById(35); Assert.assertEquals("中国", country.getCountryname()); Assert.assertEquals("ZH", country.getCountrycode()); } finally { sqlSession.close(); } //下面清空缓存再试 sqlSession = getSqlSession(); try { CountryCacheWithXmlMapper mapper = sqlSession.getMapper(CountryCacheWithXmlMapper.class); //调用 update 清空缓存 mapper.updateByPrimaryKey(new Country()); Country country = mapper.selectById(35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/CountryCacheMapper.java ================================================ package tk.mybatis.mapper.cache; import org.apache.ibatis.annotations.CacheNamespace; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.common.Mapper; /** * 只有接口时,加下面的注解即可 */ @CacheNamespace public interface CountryCacheMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/CountryCacheRefMapper.java ================================================ package tk.mybatis.mapper.cache; import org.apache.ibatis.annotations.CacheNamespaceRef; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.common.Mapper; /** * 这个例子中,在 XML 配置了缓存,这里使用注解引用 XML 中的缓存配置 *

* namespace 有两种配置方法,参考下面两行注解 */ @CacheNamespaceRef(CountryCacheRefMapper.class) //@CacheNamespaceRef(name = "tk.mybatis.mapper.cache.CountryCacheRefMapper") public interface CountryCacheRefMapper extends Mapper { /** * 定义在 XML 中的方法 * * @param id * @return */ Country selectById(Integer id); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/CountryCacheRefMapper.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/CountryCacheWithXmlMapper.java ================================================ package tk.mybatis.mapper.cache; import org.apache.ibatis.annotations.CacheNamespace; import tk.mybatis.mapper.base.Country; import tk.mybatis.mapper.common.Mapper; /** * 这个例子中,接口定义了缓存,对应的 XML 中引用这里的缓存 *

* TODO MyBatis 有 Bug,这种方式目前行不通 */ @CacheNamespace public interface CountryCacheWithXmlMapper extends Mapper { /** * 定义在 XML 中的方法 * * @param id * @return */ Country selectById(Integer id); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/CountryCacheWithXmlMapper.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/cache/mybatis-config-cache.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/CreateDB.sql ================================================ drop table user if exists; create table user ( id integer NOT NULL PRIMARY KEY, name varchar(32), lock integer, state integer ); INSERT INTO user (id, name, lock, state) VALUES (1, 'abel533', 2, 1); INSERT INTO user (id, name, lock, state) VALUES (2, 'isea533', 1, 2); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/DefaultEnumTypeHandlerTest.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.entity.Config; import java.io.IOException; import java.io.Reader; import java.util.List; /** * @author liuzh */ public class DefaultEnumTypeHandlerTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setEnumAsSimpleType(true); return config; } @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(DefaultEnumTypeHandlerTest.class.getResource("mybatis-config-defaultenumtypehandler.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return toReader(DefaultEnumTypeHandlerTest.class.getResource("CreateDB.sql")); } @Test public void testSelect() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List users = userMapper.selectAll(); Assert.assertNotNull(users); Assert.assertEquals(2, users.size()); Assert.assertEquals("abel533", users.get(0).getName()); Assert.assertEquals(LockDictEnum.unlocked, users.get(0).getLock()); Assert.assertEquals(StateDictEnum.enabled, users.get(0).getState()); Assert.assertEquals("isea533", users.get(1).getName()); Assert.assertEquals(LockDictEnum.locked, users.get(1).getLock()); Assert.assertEquals(StateDictEnum.disabled, users.get(1).getState()); User user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals(LockDictEnum.unlocked, users.get(0).getLock()); Assert.assertEquals(StateDictEnum.enabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testInsert() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setId(3); user.setName("liuzh"); user.setLock(LockDictEnum.unlocked); user.setState(StateDictEnum.enabled); Assert.assertEquals(1, userMapper.insert(user)); user = userMapper.selectByPrimaryKey(3); Assert.assertEquals("liuzh", user.getName()); Assert.assertEquals(LockDictEnum.unlocked, user.getLock()); Assert.assertEquals(StateDictEnum.enabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testUpdate() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals(LockDictEnum.unlocked, user.getLock()); Assert.assertEquals(StateDictEnum.enabled, user.getState()); user.setLock(LockDictEnum.locked); user.setState(StateDictEnum.disabled); Assert.assertEquals(1, userMapper.updateByPrimaryKey(user)); user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals(LockDictEnum.locked, user.getLock()); Assert.assertEquals(StateDictEnum.disabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testDelete() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Assert.assertEquals(1, userMapper.deleteByPrimaryKey(1)); User user = new User(); user.setState(StateDictEnum.enabled); Assert.assertEquals(0, userMapper.delete(user)); user = new User(); user.setLock(LockDictEnum.unlocked); Assert.assertEquals(0, userMapper.delete(user)); user = new User(); user.setLock(LockDictEnum.locked); user.setState(StateDictEnum.disabled); Assert.assertEquals(1, userMapper.delete(user)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/Dict.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; /** * @author liuzh */ public interface Dict { int getValue(); String getName(); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/DictTypeHandler.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * @author liuzh */ public class DictTypeHandler extends BaseTypeHandler { private final Class type; private final Dict[] enums; public DictTypeHandler(Class type) { if (type == null) { throw new IllegalArgumentException("Type argument cannot be null"); } this.type = type; this.enums = type.getEnumConstants(); if (this.enums == null) { throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type."); } } @Override public void setNonNullParameter(PreparedStatement ps, int i, Dict parameter, JdbcType jdbcType) throws SQLException { ps.setInt(i, parameter.getValue()); } private Dict convertToDict(int value) { for (Dict anEnum : enums) { if (anEnum.getValue() == value) { return anEnum; } } throw new IllegalArgumentException("Cannot convert " + value + " to " + type.getSimpleName() + " by value."); } @Override public Dict getNullableResult(ResultSet rs, String columnName) throws SQLException { int i = rs.getInt(columnName); if (rs.wasNull()) { return null; } return convertToDict(i); } @Override public Dict getNullableResult(ResultSet rs, int columnIndex) throws SQLException { int i = rs.getInt(columnIndex); if (rs.wasNull()) { return null; } return convertToDict(i); } @Override public Dict getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { int i = cs.getInt(columnIndex); if (cs.wasNull()) { return null; } return convertToDict(i); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/LockDictEnum.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; /** * @author liuzh */ public enum LockDictEnum implements Dict { locked(1), unlocked(2); private int value; private LockDictEnum(int value) { this.value = value; } @Override public int getValue() { return value; } @Override public String getName() { return name(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/StateDictEnum.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; /** * @author liuzh */ public enum StateDictEnum implements Dict { enabled(1), disabled(2); private int value; private StateDictEnum(int value) { this.value = value; } @Override public int getValue() { return value; } @Override public String getName() { return name(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/User.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; import jakarta.persistence.Id; import java.io.Serializable; /** * @author liuzh */ public class User implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String name; private LockDictEnum lock; private StateDictEnum state; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public LockDictEnum getLock() { return lock; } public void setLock(LockDictEnum lock) { this.lock = lock; } public StateDictEnum getState() { return state; } public void setState(StateDictEnum state) { this.state = state; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/UserMapper.java ================================================ package tk.mybatis.mapper.defaultenumtypehandler; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/mybatis-config-defaultenumtypehandler.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/entity/model/CountryExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity.model; import java.util.ArrayList; import java.util.List; public class CountryExample { protected String orderByClause; protected boolean distinct; protected List oredCriteria; public CountryExample() { oredCriteria = new ArrayList(); } public void or(Criteria criteria) { oredCriteria.add(criteria); } public Criteria or() { Criteria criteria = createCriteriaInternal(); oredCriteria.add(criteria); return criteria; } public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if (oredCriteria.size() == 0) { oredCriteria.add(criteria); } return criteria; } protected Criteria createCriteriaInternal() { Criteria criteria = new Criteria(); return criteria; } public void clear() { oredCriteria.clear(); orderByClause = null; distinct = false; } protected abstract static class GeneratedCriteria { protected List criteria; protected GeneratedCriteria() { super(); criteria = new ArrayList(); } protected void addCriterion(String condition) { if (condition == null) { throw new RuntimeException("Value for condition cannot be null"); } criteria.add(new Criterion(condition)); } protected void addCriterion(String condition, Object value, String property) { if (value == null) { throw new RuntimeException("Value for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value)); } protected void addCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { throw new RuntimeException("Between values for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value1, value2)); } public Criteria andIdIsNull() { addCriterion("Id is null"); return (Criteria) this; } public Criteria andIdIsNotNull() { addCriterion("Id is not null"); return (Criteria) this; } public Criteria andIdEqualTo(Integer value) { addCriterion("Id =", value, "id"); return (Criteria) this; } public Criteria andIdNotEqualTo(Integer value) { addCriterion("Id <>", value, "id"); return (Criteria) this; } public Criteria andIdGreaterThan(Integer value) { addCriterion("Id >", value, "id"); return (Criteria) this; } public Criteria andIdGreaterThanOrEqualTo(Integer value) { addCriterion("Id >=", value, "id"); return (Criteria) this; } public Criteria andIdLessThan(Integer value) { addCriterion("Id <", value, "id"); return (Criteria) this; } public Criteria andIdLessThanOrEqualTo(Integer value) { addCriterion("Id <=", value, "id"); return (Criteria) this; } public Criteria andIdIn(List values) { addCriterion("Id in", values, "id"); return (Criteria) this; } public Criteria andIdNotIn(List values) { addCriterion("Id not in", values, "id"); return (Criteria) this; } public Criteria andIdBetween(Integer value1, Integer value2) { addCriterion("Id between", value1, value2, "id"); return (Criteria) this; } public Criteria andIdNotBetween(Integer value1, Integer value2) { addCriterion("Id not between", value1, value2, "id"); return (Criteria) this; } public Criteria andCountrynameIsNull() { addCriterion("countryname is null"); return (Criteria) this; } public Criteria andCountrynameIsNotNull() { addCriterion("countryname is not null"); return (Criteria) this; } public Criteria andCountrynameEqualTo(String value) { addCriterion("countryname =", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotEqualTo(String value) { addCriterion("countryname <>", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameGreaterThan(String value) { addCriterion("countryname >", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameGreaterThanOrEqualTo(String value) { addCriterion("countryname >=", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameLessThan(String value) { addCriterion("countryname <", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameLessThanOrEqualTo(String value) { addCriterion("countryname <=", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameLike(String value) { addCriterion("countryname like", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotLike(String value) { addCriterion("countryname not like", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameIn(List values) { addCriterion("countryname in", values, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotIn(List values) { addCriterion("countryname not in", values, "countryname"); return (Criteria) this; } public Criteria andCountrynameBetween(String value1, String value2) { addCriterion("countryname between", value1, value2, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotBetween(String value1, String value2) { addCriterion("countryname not between", value1, value2, "countryname"); return (Criteria) this; } public Criteria andCountrycodeIsNull() { addCriterion("countrycode is null"); return (Criteria) this; } public Criteria andCountrycodeIsNotNull() { addCriterion("countrycode is not null"); return (Criteria) this; } public Criteria andCountrycodeEqualTo(String value) { addCriterion("countrycode =", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotEqualTo(String value) { addCriterion("countrycode <>", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeGreaterThan(String value) { addCriterion("countrycode >", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeGreaterThanOrEqualTo(String value) { addCriterion("countrycode >=", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeLessThan(String value) { addCriterion("countrycode <", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeLessThanOrEqualTo(String value) { addCriterion("countrycode <=", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeLike(String value) { addCriterion("countrycode like", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotLike(String value) { addCriterion("countrycode not like", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeIn(List values) { addCriterion("countrycode in", values, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotIn(List values) { addCriterion("countrycode not in", values, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeBetween(String value1, String value2) { addCriterion("countrycode between", value1, value2, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotBetween(String value1, String value2) { addCriterion("countrycode not between", value1, value2, "countrycode"); return (Criteria) this; } public List getAllCriteria() { return criteria; } public List getCriteria() { return criteria; } public boolean isValid() { return criteria.size() > 0; } } public static class Criteria extends GeneratedCriteria { protected Criteria() { super(); } } public static class Criterion { private String condition; private Object value; private Object secondValue; private boolean noValue; private boolean singleValue; private boolean betweenValue; private boolean listValue; private String typeHandler; protected Criterion(String condition) { super(); this.condition = condition; this.typeHandler = null; this.noValue = true; } protected Criterion(String condition, Object value, String typeHandler) { super(); this.condition = condition; this.value = value; this.typeHandler = typeHandler; if (value instanceof List) { this.listValue = true; } else { this.singleValue = true; } } protected Criterion(String condition, Object value) { this(condition, value, null); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { super(); this.condition = condition; this.value = value; this.secondValue = secondValue; this.typeHandler = typeHandler; this.betweenValue = true; } protected Criterion(String condition, Object value, Object secondValue) { this(condition, value, secondValue, null); } public String getCondition() { return condition; } public Object getSecondValue() { return secondValue; } public String getTypeHandler() { return typeHandler; } public Object getValue() { return value; } public boolean isBetweenValue() { return betweenValue; } public boolean isListValue() { return listValue; } public boolean isNoValue() { return noValue; } public boolean isSingleValue() { return singleValue; } } public String getOrderByClause() { return orderByClause; } public void setOrderByClause(String orderByClause) { this.orderByClause = orderByClause; } public List getOredCriteria() { return oredCriteria; } public boolean isDistinct() { return distinct; } public void setDistinct(boolean distinct) { this.distinct = distinct; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/CreateDB.sql ================================================ SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; -- ---------------------------- -- Table structure for user_auto_increment -- ---------------------------- DROP TABLE IF EXISTS `user_auto_increment`; CREATE TABLE `user_auto_increment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB AUTO_INCREMENT = 29 DEFAULT CHARSET = utf8; ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/GeneratedValueTest.java ================================================ package tk.mybatis.mapper.generatedvalue; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.entity.Config; import java.io.IOException; import java.io.Reader; /** * @author liuzh */ @Ignore("这个测试需要使用 MySql 数据库") public class GeneratedValueTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setOrder("AFTER"); config.setIDENTITY("MYSQL"); return config; } @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(GeneratedValueTest.class.getResource("mybatis-config-keysql-mysql.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return null; } @Test public void testUserAutoIncrement() { SqlSession sqlSession = getSqlSession(); try { UserAutoIncrementMapper mapper = sqlSession.getMapper(UserAutoIncrementMapper.class); UserAutoIncrement user = new UserAutoIncrement(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); user = mapper.selectByPrimaryKey(user.getId()); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } @Test public void testUserAutoIncrementIdentity() { SqlSession sqlSession = getSqlSession(); try { UserAutoIncrementIdentityMapper mapper = sqlSession.getMapper(UserAutoIncrementIdentityMapper.class); UserAutoIncrementIdentity user = new UserAutoIncrementIdentity(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); user = mapper.selectByPrimaryKey(user.getId()); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } @Test public void testUserSqlAfter() { SqlSession sqlSession = getSqlSession(); try { UserSqlAfterMapper mapper = sqlSession.getMapper(UserSqlAfterMapper.class); UserSqlAfter user = new UserSqlAfter(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); user = mapper.selectByPrimaryKey(user.getId()); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrement.java ================================================ package tk.mybatis.mapper.generatedvalue; import jakarta.persistence.Column; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * @author liuzh */ @Table(name = "user_auto_increment") public class UserAutoIncrement { @Id @GeneratedValue(generator = "JDBC") @Column(insertable = false) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementIdentity.java ================================================ package tk.mybatis.mapper.generatedvalue; import jakarta.persistence.*; /** * @author liuzh */ @Table(name = "user_auto_increment") public class UserAutoIncrementIdentity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(insertable = false) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementIdentityMapper.java ================================================ package tk.mybatis.mapper.generatedvalue; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserAutoIncrementIdentityMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementMapper.java ================================================ package tk.mybatis.mapper.generatedvalue; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserAutoIncrementMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/UserSqlAfter.java ================================================ package tk.mybatis.mapper.generatedvalue; import jakarta.persistence.*; /** * @author liuzh */ @Table(name = "user_auto_increment") public class UserSqlAfter { @Id @GeneratedValue( strategy = GenerationType.IDENTITY, generator = "SELECT LAST_INSERT_ID()") @Column(insertable = false) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/UserSqlAfterMapper.java ================================================ package tk.mybatis.mapper.generatedvalue; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserSqlAfterMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/generatedvalue/mybatis-config-keysql-mysql.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/helper/CamelCaseTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.helper; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.util.StringUtil; /** * @author liuzh_3nofxnp * @since 2016-08-29 22:02 */ public class CamelCaseTest { @Test public void testCamelhumpToUnderline() { Assert.assertEquals("user_id", StringUtil.camelhumpToUnderline("userId")); Assert.assertEquals("sys_user", StringUtil.camelhumpToUnderline("sysUser")); Assert.assertEquals("sys_user_role", StringUtil.camelhumpToUnderline("sysUserRole")); Assert.assertEquals("s_function", StringUtil.camelhumpToUnderline("sFunction")); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/helper/FieldHelperTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.helper; import org.junit.Test; import tk.mybatis.mapper.entity.EntityField; import tk.mybatis.mapper.mapperhelper.FieldHelper; import tk.mybatis.mapper.model.Country; import jakarta.persistence.Id; import java.beans.IntrospectionException; import java.util.List; /** * @author liuzh_3nofxnp * @since 2015-12-06 18:47 */ public class FieldHelperTest { @Test public void test1() throws IntrospectionException { List fields = FieldHelper.getFields(Country.class); for (EntityField field : fields) { System.out.println(field.getName() + " - @Id:" + field.isAnnotationPresent(Id.class) + " - javaType:" + field.getJavaType()); } System.out.println("======================================"); fields = FieldHelper.getAll(Country.class); for (EntityField field : fields) { System.out.println(field.getName() + " - @Id:" + field.isAnnotationPresent(Id.class) + " - javaType:" + field.getJavaType()); } System.out.println("======================================"); } @Test public void test2() throws IntrospectionException { Thread t1 = new Thread(new Runnable() { @Override public void run() { FieldHelper.getFields(Country.class); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { FieldHelper.getFields(Country.class); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { FieldHelper.getFields(Country.class); } }); Thread t4 = new Thread(new Runnable() { @Override public void run() { FieldHelper.getFields(Country.class); } }); t1.start(); t2.start(); t3.start(); t4.start(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/helper/FieldTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.helper; import org.junit.Test; import tk.mybatis.mapper.entity.EntityField; import tk.mybatis.mapper.mapperhelper.FieldHelper; import tk.mybatis.mapper.model.Country; import jakarta.persistence.Entity; import jakarta.persistence.Id; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.*; /** * @author liuzh_3nofxnp * @since 2015-12-28 21:30 */ public class FieldTest { /** * 通过方法获取属性 * * @param entityClass * @return */ private static List _getProperties(Class entityClass) { Map> genericMap = _getGenericTypeMap(entityClass); List entityFields = new ArrayList(); BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo(entityClass); } catch (IntrospectionException e) { throw new RuntimeException(e); } PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor desc : descriptors) { if (desc != null && !"class".equals(desc.getName())) { EntityField entityField = new EntityField(null, desc); if (desc.getReadMethod() != null && desc.getReadMethod().getGenericReturnType() != null && desc.getReadMethod().getGenericReturnType() instanceof TypeVariable) { entityField.setJavaType(genericMap.get(((TypeVariable) desc.getReadMethod().getGenericReturnType()).getName())); } else if (desc.getWriteMethod() != null && desc.getWriteMethod().getGenericParameterTypes() != null && desc.getWriteMethod().getGenericParameterTypes().length == 1 && desc.getWriteMethod().getGenericParameterTypes()[0] instanceof TypeVariable) { entityField.setJavaType(genericMap.get(((TypeVariable) desc.getWriteMethod().getGenericParameterTypes()[0]).getName())); } entityFields.add(entityField); } } return entityFields; } /** * @param entityClass */ private static Map> _getGenericTypeMap(Class entityClass) { Map> genericMap = new HashMap>(); if (entityClass == Object.class) { return genericMap; } //获取父类和泛型信息 Class superClass = entityClass.getSuperclass(); //判断superClass if (superClass != null && !superClass.equals(Object.class) && (superClass.isAnnotationPresent(Entity.class) || (!Map.class.isAssignableFrom(superClass) && !Collection.class.isAssignableFrom(superClass)))) { if (entityClass.getGenericSuperclass() instanceof ParameterizedType) { Type[] types = ((ParameterizedType) entityClass.getGenericSuperclass()).getActualTypeArguments(); TypeVariable[] typeVariables = superClass.getTypeParameters(); if (typeVariables.length > 0) { for (int i = 0; i < typeVariables.length; i++) { if (types[i] instanceof Class) { genericMap.put(typeVariables[i].getName(), (Class) types[i]); } } } } genericMap.putAll(_getGenericTypeMap(superClass)); } return genericMap; } private static void processAllColumns(Class entityClass, List fieldList, Map> genericMap) { if (fieldList == null) { fieldList = new ArrayList(); } if (entityClass == Object.class) { return; } Field[] fields = entityClass.getDeclaredFields(); for (Field field : fields) { EntityField entityField = new EntityField(field, null); if (field.getGenericType() != null && field.getGenericType() instanceof TypeVariable) { if (genericMap == null || !genericMap.containsKey(((TypeVariable) field.getGenericType()).getName())) { throw new RuntimeException(entityClass + "字段" + field.getName() + "的泛型类型无法获取!"); } else { entityField.setJavaType(genericMap.get(((TypeVariable) field.getGenericType()).getName())); } } else { entityField.setJavaType(field.getType()); } fieldList.add(entityField); } Class superClass = entityClass.getSuperclass(); Map> _genericMap = null; if (entityClass.getGenericSuperclass() instanceof ParameterizedType) { Type[] types = ((ParameterizedType) entityClass.getGenericSuperclass()).getActualTypeArguments(); TypeVariable[] typeVariables = superClass.getTypeParameters(); if (typeVariables.length > 0) { _genericMap = new HashMap>(); for (int i = 0; i < typeVariables.length; i++) { _genericMap.put(typeVariables[i].getName(), (Class) types[i]); } } } processAllColumns(superClass, fieldList, _genericMap); } // @Test public void test1() throws IntrospectionException { List fields = null;// = new ArrayList(); processAllColumns(Country.class, fields, null); for (EntityField field : fields) { System.out.println(field.getName() + " - @Id:" + field.isAnnotationPresent(Id.class) + " - javaType:" + field.getJavaType()); } System.out.println("======================================"); fields = FieldHelper.getAll(Country.class); for (EntityField field : fields) { System.out.println(field.getName() + " - @Id:" + field.isAnnotationPresent(Id.class) + " - javaType:" + field.getJavaType()); } System.out.println("======================================"); } @Test public void test2() { List fields = _getProperties(Country.class); for (EntityField field : fields) { System.out.println(field.getName() + " - @Id:" + field.isAnnotationPresent(Id.class) + " - javaType:" + field.getJavaType()); } System.out.println("======================================"); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/helper/MultipleMapperProviderTest.java ================================================ package tk.mybatis.mapper.helper; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.mapper.CountryMultipleMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import tk.mybatis.mapper.provider.base.BaseInsertProvider; import tk.mybatis.mapper.provider.base.BaseSelectProvider; import java.util.List; /** * @author yuanhao */ public class MultipleMapperProviderTest { @Test public void test() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMultipleMapper mapper = sqlSession.getMapper(CountryMultipleMapper.class); Country country = new Country(); country.setId(200); country.setCountrycode("AB"); mapper.insert(country); List countryList = mapper.select(country); Assert.assertEquals("AB", countryList.get(0).getCountrycode()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/hsqldb/HsqldbMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.hsqldb; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; /** * 扩展例子 * * @author liuzh */ @RegisterMapper public interface HsqldbMapper { /** * 单表分页查询 * * @param object * @param offset * @param limit * @return */ @SelectProvider(type = HsqldbProvider.class, method = "dynamicSQL") List selectPage(@Param("entity") T object, @Param("offset") int offset, @Param("limit") int limit); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/hsqldb/HsqldbProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.hsqldb; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.scripting.xmltags.*; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * @author liuzh */ public class HsqldbProvider extends MapperTemplate { public HsqldbProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 分页查询 * * @param ms * @return */ public SqlNode selectPage(MappedStatement ms) { Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); List sqlNodes = new ArrayList(); //静态的sql部分:select column ... from table sqlNodes.add(new StaticTextSqlNode("SELECT " + EntityHelper.getSelectColumns(entityClass) + " FROM " + tableName(entityClass))); //获取全部列 Set columnList = EntityHelper.getColumns(entityClass); List ifNodes = new ArrayList(); boolean first = true; //对所有列循环,生成[AND] column = #{property} for (EntityColumn column : columnList) { StaticTextSqlNode columnNode = new StaticTextSqlNode((first ? "" : " AND ") + column.getColumn() + " = #{entity." + column.getProperty() + "} "); if (column.getJavaType().equals(String.class)) { ifNodes.add(new IfSqlNode(columnNode, "entity." + column.getProperty() + " != null and " + "entity." + column.getProperty() + " != '' ")); } else { ifNodes.add(new IfSqlNode(columnNode, "entity." + column.getProperty() + " != null ")); } first = false; } //增加entity判断 IfSqlNode ifSqlNode = new IfSqlNode(new MixedSqlNode(ifNodes), "entity!=null"); //将if添加到 sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), ifSqlNode)); //处理分页 sqlNodes.add(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit}"), "offset==0")); sqlNodes.add(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit} OFFSET #{offset} "), "offset>0")); return new MixedSqlNode(sqlNodes); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/CreateDB.sql ================================================ drop table test_timestamp if exists; create table test_timestamp ( id integer NOT NULL PRIMARY KEY, test_date DATE, test_time TIME, test_datetime DATETIME -- 和 TIMESTAMP 相同 ); INSERT INTO test_timestamp (id, test_date, test_time, test_datetime) VALUES (1, DATE '2018-01-01', TIME '12:11:00', TIMESTAMP '2018-01-01 12:00:00'); INSERT INTO test_timestamp (id, test_date, test_time, test_datetime) VALUES (2, DATE '2018-11-11', TIME '01:59:11', TIMESTAMP '2018-02-12 17:58:12'); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/DateTimeTest.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import java.io.IOException; import java.io.Reader; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; public class DateTimeTest extends BaseTest { @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(DateTimeTest.class.getResource("mybatis-config-timestamp.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return toReader(DateTimeTest.class.getResource("CreateDB.sql")); } private String toDate(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(date); } private String toTime(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); return sdf.format(date); } private String toDatetime(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(date); } @Test public void testSelect() { SqlSession sqlSession = getSqlSession(); try { TimeModelMapper mapper = sqlSession.getMapper(TimeModelMapper.class); List list = mapper.selectAll(); Assert.assertEquals(2, list.size()); Assert.assertEquals("2018-01-01", toDate(list.get(0).getTestDate())); Assert.assertEquals("12:11:00", toTime(list.get(0).getTestTime())); Assert.assertEquals("2018-01-01 12:00:00", toDatetime(list.get(0).getTestDatetime())); Assert.assertEquals("2018-11-11", toDate(list.get(1).getTestDate())); Assert.assertEquals("01:59:11", toTime(list.get(1).getTestTime())); Assert.assertEquals("2018-02-12 17:58:12", toDatetime(list.get(1).getTestDatetime())); } finally { sqlSession.close(); } } @Test public void testInsert() { SqlSession sqlSession = getSqlSession(); try { TimeModelMapper mapper = sqlSession.getMapper(TimeModelMapper.class); TimeModel timeModel = new TimeModel(); timeModel.setId(3); Date now = new Date(); timeModel.setTestDate(now); timeModel.setTestTime(now); timeModel.setTestDatetime(now); Assert.assertEquals(1, mapper.insert(timeModel)); timeModel = mapper.selectByPrimaryKey(3); //保存后数据库中不存在时间部分 Assert.assertEquals(toDate(now), toDate(timeModel.getTestDate())); Assert.assertEquals(toDate(now) + " 00:00:00", toDatetime(timeModel.getTestDate())); //日期和时间都有 Assert.assertEquals(toTime(now), toTime(timeModel.getTestTime())); Assert.assertEquals(toDatetime(now), toDatetime(timeModel.getTestTime())); Assert.assertEquals(toDatetime(now), toDatetime(timeModel.getTestDatetime())); } finally { sqlSession.close(); } } @Test public void testSelect2() { SqlSession sqlSession = getSqlSession(); try { TimeModel2Mapper mapper = sqlSession.getMapper(TimeModel2Mapper.class); List list = mapper.selectAll(); Assert.assertEquals(2, list.size()); Assert.assertEquals("2018-01-01", toDate(list.get(0).getTestDate())); Assert.assertEquals("12:11:00", toTime(list.get(0).getTestTime())); Assert.assertEquals("2018-01-01 12:00:00", toDatetime(list.get(0).getTestDatetime())); Assert.assertEquals("2018-11-11", toDate(list.get(1).getTestDate())); Assert.assertEquals("01:59:11", toTime(list.get(1).getTestTime())); Assert.assertEquals("2018-02-12 17:58:12", toDatetime(list.get(1).getTestDatetime())); } finally { sqlSession.close(); } } @Test public void testInsert2() { SqlSession sqlSession = getSqlSession(); try { TimeModel2Mapper mapper = sqlSession.getMapper(TimeModel2Mapper.class); TimeModel2 timeModel = new TimeModel2(); timeModel.setId(3); Date now = new Date(); Timestamp now2 = new Timestamp(now.getTime()); timeModel.setTestDate(now); timeModel.setTestTime(now); timeModel.setTestDatetime(now2); Assert.assertEquals(1, mapper.insert(timeModel)); timeModel = mapper.selectByPrimaryKey(3); //保存后数据库中不存在时间部分 Assert.assertEquals(toDate(now), toDate(timeModel.getTestDate())); Assert.assertEquals(toDate(now) + " 00:00:00", toDatetime(timeModel.getTestDate())); //日期和时间都有 Assert.assertEquals(toTime(now), toTime(timeModel.getTestTime())); Assert.assertEquals(toDatetime(now), toDatetime(timeModel.getTestTime())); Assert.assertEquals(toDatetime(now), toDatetime(timeModel.getTestDatetime())); } finally { sqlSession.close(); } } @Test public void testSelect3() { SqlSession sqlSession = getSqlSession(); try { TimeModel3Mapper mapper = sqlSession.getMapper(TimeModel3Mapper.class); List list = mapper.selectAll(); Assert.assertEquals(2, list.size()); Assert.assertEquals("2018-01-01", toDate(list.get(0).getTestDate())); Assert.assertEquals("12:11:00", toTime(list.get(0).getTestTime())); Assert.assertEquals("2018-01-01 12:00:00", toDatetime(list.get(0).getTestDatetime())); Assert.assertEquals("2018-11-11", toDate(list.get(1).getTestDate())); Assert.assertEquals("01:59:11", toTime(list.get(1).getTestTime())); Assert.assertEquals("2018-02-12 17:58:12", toDatetime(list.get(1).getTestDatetime())); } finally { sqlSession.close(); } } @Test public void testInsert3() { SqlSession sqlSession = getSqlSession(); try { TimeModel3Mapper mapper = sqlSession.getMapper(TimeModel3Mapper.class); TimeModel3 timeModel = new TimeModel3(); timeModel.setId(3); Date now = new Date(); timeModel.setTestDate(now); timeModel.setTestTime(now); timeModel.setTestDatetime(now); /* insert 日志能明显看到制定 jdbcType 后的区别 DEBUG [main] - ==> Preparing: INSERT INTO test_timestamp ( id,test_date,test_time,test_datetime ) VALUES( ?,?,?,? ) DEBUG [main] - ==> Parameters: 3(Integer), 2018-02-25(Date), 11:50:18(Time), 2018-02-25 11:50:18.263(Timestamp) */ Assert.assertEquals(1, mapper.insert(timeModel)); timeModel = mapper.selectByPrimaryKey(3); //保存后数据库中不存在时间部分 Assert.assertEquals(toDate(now), toDate(timeModel.getTestDate())); Assert.assertEquals(toDate(now) + " 00:00:00", toDatetime(timeModel.getTestDate())); //时间 Assert.assertEquals(toTime(now), toTime(timeModel.getTestTime())); //由于插入数据库时指定的 jdbcType=TIME,所以下面是没有日期部分的 Assert.assertEquals("1970-01-01 " + toTime(now), toDatetime(timeModel.getTestTime())); Assert.assertEquals(toDatetime(now), toDatetime(timeModel.getTestDatetime())); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; import java.util.Date; /** * @author liuzh */ @Table(name = "test_timestamp") public class TimeModel implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private Date testDate; private Date testTime; private Date testDatetime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Date getTestDate() { return testDate; } public void setTestDate(Date testDate) { this.testDate = testDate; } public Date getTestTime() { return testTime; } public void setTestTime(Date testTime) { this.testTime = testTime; } public Date getTestDatetime() { return testDatetime; } public void setTestDatetime(Date testDatetime) { this.testDatetime = testDatetime; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel2.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; import java.sql.Timestamp; import java.util.Date; /** * @author liuzh */ @Table(name = "test_timestamp") public class TimeModel2 implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private Date testDate; private Date testTime; private Timestamp testDatetime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Date getTestDate() { return testDate; } public void setTestDate(Date testDate) { this.testDate = testDate; } public Timestamp getTestDatetime() { return testDatetime; } public void setTestDatetime(Timestamp testDatetime) { this.testDatetime = testDatetime; } public Date getTestTime() { return testTime; } public void setTestTime(Date testTime) { this.testTime = testTime; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel2Mapper.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface TimeModel2Mapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel3.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.annotation.ColumnType; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; import java.util.Date; /** * @author liuzh */ @Table(name = "test_timestamp") public class TimeModel3 implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; @ColumnType(jdbcType = JdbcType.DATE) private Date testDate; @ColumnType(jdbcType = JdbcType.TIME) private Date testTime; @ColumnType(jdbcType = JdbcType.TIMESTAMP) private Date testDatetime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Date getTestDate() { return testDate; } public void setTestDate(Date testDate) { this.testDate = testDate; } public Date getTestDatetime() { return testDatetime; } public void setTestDatetime(Date testDatetime) { this.testDatetime = testDatetime; } public Date getTestTime() { return testTime; } public void setTestTime(Date testTime) { this.testTime = testTime; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel3Mapper.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface TimeModel3Mapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModelMapper.java ================================================ package tk.mybatis.mapper.issues._216_datetime; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface TimeModelMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/mybatis-config-timestamp.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/issues/package-info.java ================================================ /** * 通过 issues 提交的问题 */ package tk.mybatis.mapper.issues; ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/CreateDB.sql ================================================ SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; -- ---------------------------- -- Table structure for user_auto_increment -- ---------------------------- DROP TABLE IF EXISTS `user_auto_increment`; CREATE TABLE `user_auto_increment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB AUTO_INCREMENT = 29 DEFAULT CHARSET = utf8; ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/KeySqlTest.java ================================================ package tk.mybatis.mapper.keysql; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import java.io.IOException; import java.io.Reader; /** * @author liuzh */ @Ignore("这个测试需要使用 MySql 数据库") public class KeySqlTest extends BaseTest { @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(KeySqlTest.class.getResource("mybatis-config-keysql-mysql.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return null; } @Test public void testUserAutoIncrement() { SqlSession sqlSession = getSqlSession(); try { UserAutoIncrementMapper mapper = sqlSession.getMapper(UserAutoIncrementMapper.class); UserAutoIncrement user = new UserAutoIncrement(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); user = mapper.selectByPrimaryKey(user.getId()); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } @Test public void testUserAutoIncrementIdentity() { SqlSession sqlSession = getSqlSession(); try { UserAutoIncrementIdentityMapper mapper = sqlSession.getMapper(UserAutoIncrementIdentityMapper.class); UserAutoIncrementIdentity user = new UserAutoIncrementIdentity(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); user = mapper.selectByPrimaryKey(user.getId()); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } @Test public void testUserSqlAfter() { SqlSession sqlSession = getSqlSession(); try { UserSqlAfterMapper mapper = sqlSession.getMapper(UserSqlAfterMapper.class); UserSqlAfter user = new UserSqlAfter(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertNotNull(user.getId()); user = mapper.selectByPrimaryKey(user.getId()); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } @Test public void testUserSqlBefore() { SqlSession sqlSession = getSqlSession(); try { UserSqlBeforeMapper mapper = sqlSession.getMapper(UserSqlBeforeMapper.class); UserSqlBefore user = new UserSqlBefore(); user.setName("liuzh"); Assert.assertEquals(1, mapper.insert(user)); Assert.assertEquals(new Integer(12345), user.getId()); user = mapper.selectByPrimaryKey(12345); Assert.assertEquals("liuzh", user.getName()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrement.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.annotation.KeySql; import jakarta.persistence.Column; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * @author liuzh */ @Table(name = "user_auto_increment") public class UserAutoIncrement { @Id @KeySql(useGeneratedKeys = true) @Column(insertable = false) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementIdentity.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.code.IdentityDialect; import jakarta.persistence.Column; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * @author liuzh */ @Table(name = "user_auto_increment") public class UserAutoIncrementIdentity { @Id @KeySql(dialect = IdentityDialect.MYSQL) @Column(insertable = false) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementIdentityMapper.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserAutoIncrementIdentityMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementMapper.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserAutoIncrementMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserSqlAfter.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.code.ORDER; import jakarta.persistence.Column; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * @author liuzh */ @Table(name = "user_auto_increment") public class UserSqlAfter { @Id @KeySql(sql = "SELECT LAST_INSERT_ID()", order = ORDER.AFTER) @Column(insertable = false) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserSqlAfterMapper.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserSqlAfterMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserSqlBefore.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.code.ORDER; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * @author liuzh */ @Table(name = "user") public class UserSqlBefore { @Id @KeySql(sql = "select 12345", order = ORDER.BEFORE) private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/UserSqlBeforeMapper.java ================================================ package tk.mybatis.mapper.keysql; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserSqlBeforeMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/keysql/mybatis-config-keysql-mysql.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CachedCountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.hsqldb.HsqldbMapper; import tk.mybatis.mapper.model.Country; /** * Created by liuzh on 2014/11/19. */ //@CacheNamespace public interface CachedCountryMapper extends Mapper, HsqldbMapper { int selectCache(int id); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/Country2Mapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.Country2; /** * Created by liuzh on 2014/11/19. */ public interface Country2Mapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CountryIMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.CountryI; /** * Created by liuzh on 2014/11/19. */ public interface CountryIMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CountryJDBCMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.SqlServerMapper; import tk.mybatis.mapper.model.CountryJDBC; /** * Created by liuzh on 2014/11/19. */ public interface CountryJDBCMapper extends SqlServerMapper { int insertA(CountryJDBC countryJDBC); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.IdsMapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.MySqlMapper; import tk.mybatis.mapper.hsqldb.HsqldbMapper; import tk.mybatis.mapper.model.Country; /** * Created by liuzh on 2014/11/19. */ public interface CountryMapper extends Mapper, HsqldbMapper, MySqlMapper, IdsMapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CountryMultipleMapper.java ================================================ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.base.insert.InsertMapper; import tk.mybatis.mapper.common.base.select.SelectMapper; import tk.mybatis.mapper.model.Country; public interface CountryMultipleMapper extends MultipleCommonMapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CountryTMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.CountryT; /** * Created by liuzh on 2014/11/19. */ public interface CountryTMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/CountryVersionMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.CountryVersion; /** * Created by liuzh on 2014/11/19. */ public interface CountryVersionMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/JDBCMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.MySqlMapper; import tk.mybatis.mapper.model.Country; /** * Created by liuzh_3nofxnp on 2015/8/26. */ public interface JDBCMapper extends MySqlMapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/MultipleCommonMapper.java ================================================ package tk.mybatis.mapper.mapper; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.provider.base.BaseInsertProvider; import tk.mybatis.mapper.provider.base.BaseSelectProvider; import java.util.List; @RegisterMapper public interface MultipleCommonMapper { @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") List select(T record); @InsertProvider(type = BaseInsertProvider.class, method = "dynamicSQL") int insert(T record); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/MybatisHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.io.IOException; import java.io.Reader; import java.sql.Connection; /** * Description: MybatisHelper * Author: liuzh * Update: liuzh(2014-06-06 13:33) */ public class MybatisHelper { private static SqlSessionFactory sqlSessionFactory; static { try { //创建SqlSessionFactory Reader reader = Resources.getResourceAsReader("mybatis-java.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); reader.close(); //创建数据库 SqlSession session = null; try { session = sqlSessionFactory.openSession(); //创建一个MapperHelper MapperHelper mapperHelper = new MapperHelper(); //特殊配置 Config config = new Config(); // 主键自增回写方法,默认值MYSQL,详细说明请看文档 config.setIDENTITY("HSQLDB"); // 支持方法上的注解 // 3.3.1版本增加 config.setEnableMethodAnnotation(true); config.setNotEmpty(true); //校验Example中的类型是否一致 config.setCheckExampleEntityClass(true); //启用简单类型 config.setUseSimpleType(true); config.setEnumAsSimpleType(true); // 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle // 可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName, PropertyName //config.setSeqFormat("NEXT VALUE FOR {0}"); // 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename //config.setCatalog(""); // 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename // 如果同时设置了catalog,优先使用catalog.tablename //config.setSchema(""); // 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER) //config.setOrder("AFTER"); //自动关键字 - mysql //config.setWrapKeyword("`{0}`"); //使用 javaType config.setUseJavaType(true); //设置配置 mapperHelper.setConfig(config); //配置完成后,执行下面的操作 mapperHelper.processConfiguration(session.getConfiguration()); //OK - mapperHelper的任务已经完成,可以不管了 Connection conn = session.getConnection(); reader = Resources.getResourceAsReader("CreateDB.sql"); ScriptRunner runner = new ScriptRunner(conn); runner.setLogWriter(null); runner.runScript(reader); reader.close(); } finally { if (session != null) { session.close(); } } } catch (IOException e) { e.printStackTrace(); } } /** * 获取Session * * @return */ public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/TbUserLogicDeleteMapper.java ================================================ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.TbUserLogicDelete; public interface TbUserLogicDeleteMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/TbUserMapper.java ================================================ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.TbUser; public interface TbUserMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/UserInfoAbleMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.UserInfoAble; /** * Created by liuzh on 2014/11/19. */ public interface UserInfoAbleMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/UserInfoMapMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.UserInfoMap; /** * Created by liuzh on 2014/11/19. */ public interface UserInfoMapMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/UserInfoMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.UserInfo; /** * Created by liuzh on 2014/11/19. */ public interface UserInfoMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/UserLogin2Mapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.UserLogin2; /** * Created by liuzh on 2014/11/19. */ public interface UserLogin2Mapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/mapper/UserLoginMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.model.UserLogin; /** * Created by liuzh on 2014/11/19. */ public interface UserLoginMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/BaseLogicDelete.java ================================================ package tk.mybatis.mapper.model; import tk.mybatis.mapper.annotation.LogicDelete; import jakarta.persistence.Column; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; public class BaseLogicDelete { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected Integer id; @LogicDelete(isDeletedValue = 0, notDeletedValue = 1) @Column(name = "is_valid") protected Integer isValid; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getIsValid() { return isValid; } public void setIsValid(Integer isValid) { this.isValid = isValid; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import tk.mybatis.mapper.annotation.Order; import tk.mybatis.mapper.entity.IDynamicTableName; import jakarta.persistence.Column; import jakarta.persistence.Transient; import java.io.Serializable; import java.util.List; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ public class Country extends Entity implements Serializable, IDynamicTableName { private static final long serialVersionUID = -1626761012846137805L; List list; @Column @Order(value = "DESC", priority = 2) private String countryname; private String countrycode; @Transient private String dynamicTableName123; public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } @Override @Transient public String getDynamicTableName() { return dynamicTableName123; } public List getList() { return list; } public void setList(List list) { this.list = list; } public void setDynamicTableName123(String dynamicTableName) { this.dynamicTableName123 = dynamicTableName; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/Country2.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ public class Country2 { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String countryname; private String countrycode; @Override public String toString() { return "Country{" + "id=" + id + ", countryname='" + countryname + '\'' + ", countrycode='" + countrycode + '\'' + '}'; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/CountryExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import java.util.ArrayList; import java.util.List; public class CountryExample { /** * This field was generated by MyBatis Generator. * This field corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ protected String orderByClause; /** * This field was generated by MyBatis Generator. * This field corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ protected boolean distinct; /** * This field was generated by MyBatis Generator. * This field corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ protected List oredCriteria; /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public CountryExample() { oredCriteria = new ArrayList(); } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public void or(Criteria criteria) { oredCriteria.add(criteria); } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public Criteria or() { Criteria criteria = createCriteriaInternal(); oredCriteria.add(criteria); return criteria; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if (oredCriteria.size() == 0) { oredCriteria.add(criteria); } return criteria; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ protected Criteria createCriteriaInternal() { Criteria criteria = new Criteria(); return criteria; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public void clear() { oredCriteria.clear(); orderByClause = null; distinct = false; } /** * This class was generated by MyBatis Generator. * This class corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ protected abstract static class GeneratedCriteria { protected List criteria; protected GeneratedCriteria() { super(); criteria = new ArrayList(); } protected void addCriterion(String condition) { if (condition == null) { throw new RuntimeException("Value for condition cannot be null"); } criteria.add(new Criterion(condition)); } protected void addCriterion(String condition, Object value, String property) { if (value == null) { throw new RuntimeException("Value for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value)); } protected void addCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { throw new RuntimeException("Between values for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value1, value2)); } public Criteria andIdIsNull() { addCriterion("Id is null"); return (Criteria) this; } public Criteria andIdIsNotNull() { addCriterion("Id is not null"); return (Criteria) this; } public Criteria andIdEqualTo(Integer value) { addCriterion("Id =", value, "id"); return (Criteria) this; } public Criteria andIdNotEqualTo(Integer value) { addCriterion("Id <>", value, "id"); return (Criteria) this; } public Criteria andIdGreaterThan(Integer value) { addCriterion("Id >", value, "id"); return (Criteria) this; } public Criteria andIdGreaterThanOrEqualTo(Integer value) { addCriterion("Id >=", value, "id"); return (Criteria) this; } public Criteria andIdLessThan(Integer value) { addCriterion("Id <", value, "id"); return (Criteria) this; } public Criteria andIdLessThanOrEqualTo(Integer value) { addCriterion("Id <=", value, "id"); return (Criteria) this; } public Criteria andIdIn(List values) { addCriterion("Id in", values, "id"); return (Criteria) this; } public Criteria andIdNotIn(List values) { addCriterion("Id not in", values, "id"); return (Criteria) this; } public Criteria andIdBetween(Integer value1, Integer value2) { addCriterion("Id between", value1, value2, "id"); return (Criteria) this; } public Criteria andIdNotBetween(Integer value1, Integer value2) { addCriterion("Id not between", value1, value2, "id"); return (Criteria) this; } public Criteria andCountrynameIsNull() { addCriterion("countryname is null"); return (Criteria) this; } public Criteria andCountrynameIsNotNull() { addCriterion("countryname is not null"); return (Criteria) this; } public Criteria andCountrynameEqualTo(String value) { addCriterion("countryname =", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotEqualTo(String value) { addCriterion("countryname <>", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameGreaterThan(String value) { addCriterion("countryname >", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameGreaterThanOrEqualTo(String value) { addCriterion("countryname >=", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameLessThan(String value) { addCriterion("countryname <", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameLessThanOrEqualTo(String value) { addCriterion("countryname <=", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameLike(String value) { addCriterion("countryname like", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotLike(String value) { addCriterion("countryname not like", value, "countryname"); return (Criteria) this; } public Criteria andCountrynameIn(List values) { addCriterion("countryname in", values, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotIn(List values) { addCriterion("countryname not in", values, "countryname"); return (Criteria) this; } public Criteria andCountrynameBetween(String value1, String value2) { addCriterion("countryname between", value1, value2, "countryname"); return (Criteria) this; } public Criteria andCountrynameNotBetween(String value1, String value2) { addCriterion("countryname not between", value1, value2, "countryname"); return (Criteria) this; } public Criteria andCountrycodeIsNull() { addCriterion("countrycode is null"); return (Criteria) this; } public Criteria andCountrycodeIsNotNull() { addCriterion("countrycode is not null"); return (Criteria) this; } public Criteria andCountrycodeEqualTo(String value) { addCriterion("countrycode =", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotEqualTo(String value) { addCriterion("countrycode <>", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeGreaterThan(String value) { addCriterion("countrycode >", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeGreaterThanOrEqualTo(String value) { addCriterion("countrycode >=", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeLessThan(String value) { addCriterion("countrycode <", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeLessThanOrEqualTo(String value) { addCriterion("countrycode <=", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeLike(String value) { addCriterion("countrycode like", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotLike(String value) { addCriterion("countrycode not like", value, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeIn(List values) { addCriterion("countrycode in", values, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotIn(List values) { addCriterion("countrycode not in", values, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeBetween(String value1, String value2) { addCriterion("countrycode between", value1, value2, "countrycode"); return (Criteria) this; } public Criteria andCountrycodeNotBetween(String value1, String value2) { addCriterion("countrycode not between", value1, value2, "countrycode"); return (Criteria) this; } public List getAllCriteria() { return criteria; } public List getCriteria() { return criteria; } public boolean isValid() { return criteria.size() > 0; } } /** * This class was generated by MyBatis Generator. * This class corresponds to the database table country * * @mbggenerated do_not_delete_during_merge Sat Mar 07 11:52:52 CST 2015 */ public static class Criteria extends GeneratedCriteria { protected Criteria() { super(); } } /** * This class was generated by MyBatis Generator. * This class corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public static class Criterion { private String condition; private Object value; private Object secondValue; private boolean noValue; private boolean singleValue; private boolean betweenValue; private boolean listValue; private String typeHandler; protected Criterion(String condition) { super(); this.condition = condition; this.typeHandler = null; this.noValue = true; } protected Criterion(String condition, Object value, String typeHandler) { super(); this.condition = condition; this.value = value; this.typeHandler = typeHandler; if (value instanceof List) { this.listValue = true; } else { this.singleValue = true; } } protected Criterion(String condition, Object value) { this(condition, value, null); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { super(); this.condition = condition; this.value = value; this.secondValue = secondValue; this.typeHandler = typeHandler; this.betweenValue = true; } protected Criterion(String condition, Object value, Object secondValue) { this(condition, value, secondValue, null); } public String getCondition() { return condition; } public Object getSecondValue() { return secondValue; } public String getTypeHandler() { return typeHandler; } public Object getValue() { return value; } public boolean isBetweenValue() { return betweenValue; } public boolean isListValue() { return listValue; } public boolean isNoValue() { return noValue; } public boolean isSingleValue() { return singleValue; } } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public String getOrderByClause() { return orderByClause; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public void setOrderByClause(String orderByClause) { this.orderByClause = orderByClause; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public List getOredCriteria() { return oredCriteria; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public boolean isDistinct() { return distinct; } /** * This method was generated by MyBatis Generator. * This method corresponds to the database table country * * @mbggenerated Sat Mar 07 11:52:52 CST 2015 */ public void setDistinct(boolean distinct) { this.distinct = distinct; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/CountryI.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import tk.mybatis.mapper.annotation.NameStyle; import tk.mybatis.mapper.code.Style; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ @NameStyle(Style.camelhump) public class CountryI { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String countryname; private String countrycode; @Override public String toString() { return "Country{" + "id=" + id + ", countryname='" + countryname + '\'' + ", countrycode='" + countrycode + '\'' + '}'; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/CountryJDBC.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ @Table(name = "country") public class CountryJDBC { @Id @GeneratedValue(generator = "JDBC") private Integer id; private String countryname; private String countrycode; @Override public String toString() { return "Country{" + "id=" + id + ", countryname='" + countryname + '\'' + ", countrycode='" + countrycode + '\'' + '}'; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/CountryT.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.Id; import jakarta.persistence.Transient; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ public class CountryT { @Id private Integer id; private String countryname; @Transient private String countrycode; @Override public String toString() { return "Country{" + "id=" + id + ", countryname='" + countryname + '\'' + ", countrycode='" + countrycode + '\'' + '}'; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/CountryVersion.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import tk.mybatis.mapper.annotation.Version; import jakarta.persistence.Table; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ @Table(name = "country") public class CountryVersion extends Country { @Version private Integer version; public Integer getVersion() { return version; } public void setVersion(Integer version) { this.version = version; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/Entity.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import tk.mybatis.mapper.annotation.Order; import jakarta.persistence.Id; import jakarta.persistence.Transient; import java.io.Serializable; /** * @author liuzh_3nofxnp * @since 2015-12-06 10:31 */ public class Entity { //这里的a,b,c,d仅用来测试FieldHelper中的静态字段 private static Integer a, b, c, d; @Order(value = "desc", priority = 1) private ID id; @Transient private NAME name; @Id public ID getId() { return id; } public void setId(ID id) { this.id = id; } public NAME getName() { return name; } public void setName(NAME name) { this.name = name; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/TbUser.java ================================================ package tk.mybatis.mapper.model; import jakarta.persistence.*; @Table(name = "tb_user") public class TbUser { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "username") private String username; @Column(name = "password") private String password; @Column(name = "is_valid") private Integer isValid; @Override public String toString() { return "TbUser{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", isValid=" + isValid + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getIsValid() { return isValid; } public void setIsValid(Integer isValid) { this.isValid = isValid; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/TbUserLogicDelete.java ================================================ package tk.mybatis.mapper.model; import jakarta.persistence.Column; import jakarta.persistence.Table; @Table(name = "tb_user") public class TbUserLogicDelete extends BaseLogicDelete { @Column(name = "username") private String username; @Column(name = "password") private String password; @Override public String toString() { return "TbUser{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", isValid=" + isValid + '}'; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserInfo.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import java.io.Serializable; /** * Created by liuzh on 2014/11/21. */ public class UserInfo implements Serializable { private static final long serialVersionUID = -7703830119762722918L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String username; private String password; private String usertype; private String realname; private String qq; private String email; private String address; private String tel; @Override public String toString() { return "UserInfo{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", usertype='" + usertype + '\'' + ", realname='" + realname + '\'' + ", qq='" + qq + '\'' + ", email='" + email + '\'' + ", address='" + address + '\'' + ", tel='" + tel + '\'' + '}'; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getQq() { return qq; } public void setQq(String qq) { this.qq = qq; } public String getRealname() { return realname; } public void setRealname(String realname) { this.realname = realname; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUsertype() { return usertype; } public void setUsertype(String usertype) { this.usertype = usertype; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserInfoAble.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.*; import java.io.Serializable; /** * Created by liuzh on 2014/11/21. */ @Table(name = "user_info") public class UserInfoAble extends UserParent implements Serializable { private static final long serialVersionUID = -7703830119762722918L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String username; private String password; private String usertype; private String realname; private String qq; private String email; private String tel; @Override public String toString() { return "UserInfo{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", usertype='" + usertype + '\'' + ", realname='" + realname + '\'' + ", qq='" + qq + '\'' + ", email='" + email + '\'' + ", tel='" + tel + '\'' + '}'; } public String getEmail() { return email; } @Column(insertable = false) public void setEmail(String email) { this.email = email; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getQq() { return qq; } public void setQq(String qq) { this.qq = qq; } public String getRealname() { return realname; } public void setRealname(String realname) { this.realname = realname; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUsertype() { return usertype; } public void setUsertype(String usertype) { this.usertype = usertype; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserInfoMap.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import java.io.Serializable; import java.util.HashMap; /** * Created by liuzh on 2014/11/21. */ public class UserInfoMap extends HashMap implements Serializable { private static final long serialVersionUID = -7703830119762722918L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String userName; private String password; private String userType; private String realName; @Override public String toString() { final StringBuffer sb = new StringBuffer("UserInfoMap{"); sb.append("id=").append(id); sb.append(", userName='").append(getUserName()).append('\''); sb.append(", password='").append(getPassword()).append('\''); sb.append(", userType='").append(getUserType()).append('\''); sb.append(", realName='").append(getRealName()).append('\''); sb.append('}'); return sb.toString(); } public Integer getId() { return (Integer) get("id"); } public void setId(Integer id) { put("id", id); } public String getPassword() { return get("password") != null ? (String) get("password") : null; } public void setPassword(String password) { put("password", password); } public String getRealName() { return get("realName") != null ? (String) get("realName") : null; } public void setRealName(String realName) { put("realName", realName); } public String getUserName() { return get("userName") != null ? (String) get("userName") : null; } public void setUserName(String userName) { put("userName", userName); } public String getUserType() { return get("userType") != null ? (String) get("userType") : null; } public void setUserType(String userType) { put("userType", userType); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserLogin.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import java.util.Date; /** * Created by liuzh on 2014/11/21. */ public class UserLogin { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer logid; @Id private String username; private Date logindate; private String loginip; @Override public String toString() { return "UserLogin{" + "logid=" + logid + ", username='" + username + '\'' + ", logindate=" + logindate + ", loginip='" + loginip + '\'' + '}'; } public Integer getLogid() { return logid; } public void setLogid(Integer logid) { this.logid = logid; } public Date getLogindate() { return logindate; } public void setLogindate(Date logindate) { this.logindate = logindate; } public String getLoginip() { return loginip; } public void setLoginip(String loginip) { this.loginip = loginip; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserLogin2.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.Table; import java.util.Date; /** * Created by liuzh on 2014/11/21. */ @Table(name = "USER_LOGIN") public class UserLogin2 extends UserLogin2Key { private Date logindate; private String loginip; public Date getLogindate() { return logindate; } public void setLogindate(Date logindate) { this.logindate = logindate; } public String getLoginip() { return loginip; } public void setLoginip(String loginip) { this.loginip = loginip; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserLogin2Key.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; /** * Created by liuzh on 2014/11/21. */ public class UserLogin2Key { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer logid; @Id private String username; @Override public String toString() { return "UserLogin2Key{" + "logid=" + logid + ", username='" + username + '\'' + '}'; } public Integer getLogid() { return logid; } public void setLogid(Integer logid) { this.logid = logid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/model/UserParent.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.model; import jakarta.persistence.Column; /** * @author liuzh_3nofxnp * @since 2016-08-29 22:36 */ public class UserParent { @Column(updatable = false) private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/rawresultmap/CreateDB.sql ================================================ drop table user if exists; create table user ( id integer NOT NULL PRIMARY KEY, name varchar(32), user_name varchar(32), email varchar(32), age__int__aa integer, create_time datetime ); INSERT INTO user (id, name, user_name, email, age__int__aa, create_time) VALUES (1, 'trifolium1', 'wang1', 'email1', 23, now()); INSERT INTO user (id, name, user_name, email, age__int__aa, create_time) VALUES (2, 'trifolium2', 'wang2', 'email2', 32, now()); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/rawresultmap/RawResultMapTest.java ================================================ package tk.mybatis.mapper.rawresultmap; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.List; import java.util.Map; /** * @author liuzh */ public class RawResultMapTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setStyle(Style.normal); config.setEnableBaseResultMapFlag(true); return config; } @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(RawResultMapTest.class.getResource("mybatis-config-rawresultmap.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { URL url = RawResultMapTest.class.getResource("CreateDB.sql"); return toReader(url); } @Test public void testSelect() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); List users; System.out.println("------selectAll------"); users = mapper.selectAll(); users.forEach(u -> { System.out.println(u); Assert.assertNotNull(u.getUname()); Assert.assertNotNull(u.getAge()); Assert.assertNotNull(u.getCreateTime()); Assert.assertNull(u.getEmail()); }); System.out.println("------------"); System.out.println("------selectRawAnnotation------"); users = mapper.selectRawAnnotation(); users.forEach(u -> { System.out.println(u); Assert.assertNotNull(u.getUname()); Assert.assertNotNull(u.getAge()); Assert.assertNotNull(u.getCreateTime()); Assert.assertNotNull(u.getEmail()); }); System.out.println("------------"); System.out.println("------fetchRawResultMap------"); users = mapper.fetchRawResultMap(); users.forEach(u -> { System.out.println(u); Assert.assertNotNull(u.getUname()); Assert.assertNull(u.getAge()); Assert.assertNotNull(u.getCreateTime()); Assert.assertNotNull(u.getEmail()); }); System.out.println("------------"); System.out.println("------fetchRawResultType------"); users = mapper.fetchRawResultType(); users.forEach(u -> { System.out.println(u); Assert.assertNotNull(u.getUname()); Assert.assertNotNull(u.getAge()); Assert.assertNotNull(u.getCreateTime()); Assert.assertNotNull(u.getEmail()); }); System.out.println("------------"); System.out.println("------getMapUser------"); Map mapUser = mapper.getMapUser(); System.out.println(mapUser); System.out.println("------------"); Integer x = mapper.selectCount2(); System.out.println(x); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/rawresultmap/User.java ================================================ package tk.mybatis.mapper.rawresultmap; import tk.mybatis.mapper.annotation.NameStyle; import tk.mybatis.mapper.code.Style; import jakarta.persistence.Column; import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.persistence.Transient; import java.util.Date; /** * @author liuzh */ @NameStyle(Style.camelhump) @Table(name = "user") public class User { @Id private Integer id; private String name; @Column(name = "user_name") private String uname; @Column(name = "age__int__aa") private Integer age; private Date createTime; @Transient private String email; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", uname='" + uname + '\'' + ", age=" + age + ", createTime=" + createTime + ", email='" + email + '\'' + '}'; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/rawresultmap/UserMapper.java ================================================ package tk.mybatis.mapper.rawresultmap; import org.apache.ibatis.annotations.Select; import tk.mybatis.mapper.common.BaseMapper; import java.util.List; import java.util.Map; /** * @author liuzh */ public interface UserMapper extends BaseMapper { @Select("SELECT * FROM user") List selectRawAnnotation(); List fetchRawResultType(); List fetchRawResultMap(); Map getMapUser(); Integer selectCount2(); } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/rawresultmap/UserMapper.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/rawresultmap/mybatis-config-rawresultmap.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/able/TestBasicAble.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.able; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.UserInfoAbleMapper; import tk.mybatis.mapper.model.UserInfoAble; /** * 测试增删改查 * * @author liuzh */ public class TestBasicAble { /** * 新增 */ @Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoAbleMapper mapper = sqlSession.getMapper(UserInfoAbleMapper.class); UserInfoAble userInfo = new UserInfoAble(); userInfo.setUsername("abel533"); userInfo.setPassword("123456"); userInfo.setUsertype("2"); userInfo.setEmail("abel533@gmail.com");//insert=false Assert.assertEquals(1, mapper.insert(userInfo)); Assert.assertNotNull(userInfo.getId()); userInfo = mapper.selectByPrimaryKey(userInfo.getId()); //email没有插入 Assert.assertNull(userInfo.getEmail()); } finally { sqlSession.rollback(); sqlSession.close(); } } /** * 根据主键全更新 */ @Test public void testUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoAbleMapper mapper = sqlSession.getMapper(UserInfoAbleMapper.class); UserInfoAble userInfo = mapper.selectByPrimaryKey(2); Assert.assertNotNull(userInfo); userInfo.setUsertype(null); userInfo.setEmail("abel533@gmail.com"); userInfo.setAddress("这个地址不会更新进去");//update=false //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKey(userInfo)); userInfo = mapper.selectByPrimaryKey(userInfo); Assert.assertNull(userInfo.getUsertype()); Assert.assertNotEquals("这个地址不会更新进去", userInfo.getAddress()); Assert.assertEquals("abel533@gmail.com", userInfo.getEmail()); } finally { sqlSession.rollback(); sqlSession.close(); } } /** * 根据主键更新非null */ @Test public void testUpdateByPrimaryKeySelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoAbleMapper mapper = sqlSession.getMapper(UserInfoAbleMapper.class); UserInfoAble userInfo = mapper.selectByPrimaryKey(1); Assert.assertNotNull(userInfo); userInfo.setUsertype(null); userInfo.setPassword(null); userInfo.setAddress("这个地址不会更新进去"); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(userInfo)); userInfo = mapper.selectByPrimaryKey(1); Assert.assertEquals("1", userInfo.getUsertype()); Assert.assertEquals("12345678", userInfo.getPassword()); Assert.assertNotEquals("这个地址不会更新进去", userInfo.getAddress()); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestCache.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.mapper.CachedCountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * 通过实体类属性进行查询 * * @author liuzh */ public class TestCache { @Test public void testCache() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CachedCountryMapper mapper = sqlSession.getMapper(CachedCountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); //第一次查询,会被缓存 country = mapper.selectOne(country); //只有close才会真正缓存,而不是用一级缓存 sqlSession.close(); //====================================================================== sqlSession = MybatisHelper.getSqlSession(); mapper = sqlSession.getMapper(CachedCountryMapper.class); country = new Country(); country.setCountrycode("CN"); //第二次查询,会使用第一次的缓存 country = mapper.selectOne(country); //只有close才会真正缓存,而不是用一级缓存 sqlSession.close(); } finally { sqlSession.close(); } } @Test public void testCache2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { //第一次查询,会被缓存 sqlSession.selectOne("selectCache", 35); //只有close才会真正缓存,而不是用一级缓存 sqlSession.close(); //====================================================================== sqlSession = MybatisHelper.getSqlSession(); sqlSession.selectOne("selectCache", 35); sqlSession.close(); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestDeleteByPrimaryKey.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.io.IOException; import java.io.Reader; import java.sql.Connection; import java.util.HashMap; import java.util.Map; /** * 通过主键删除 * * @author liuzh */ public class TestDeleteByPrimaryKey { @Before public void setupDB() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Connection conn = sqlSession.getConnection(); Reader reader = Resources.getResourceAsReader("CreateDB.sql"); ScriptRunner runner = new ScriptRunner(conn); runner.setLogWriter(null); runner.runScript(reader); reader.close(); } catch (IOException e) {} finally { sqlSession.close(); } } /** * 主要测试删除 */ @Test public void testDynamicDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //查询总数 Assert.assertEquals(183, mapper.selectCount(new Country())); //查询100 Country country = mapper.selectByPrimaryKey(100); //根据主键删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(100)); //查询总数 Assert.assertEquals(182, mapper.selectCount(new Country())); //插入 Assert.assertEquals(1, mapper.insert(country)); } finally { sqlSession.close(); } } /** * 删除不存在的主键 */ @Test public void testDynamicDeleteZero() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //根据主键删除 Assert.assertEquals(0, mapper.deleteByPrimaryKey(null)); Assert.assertEquals(0, mapper.deleteByPrimaryKey(-100)); Assert.assertEquals(0, mapper.deleteByPrimaryKey(0)); Assert.assertEquals(0, mapper.deleteByPrimaryKey(1000)); } finally { sqlSession.close(); } } /** * 对象包含主键即可 */ @Test public void testDynamicDeleteEntity() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(100); Assert.assertEquals(1, mapper.deleteByPrimaryKey(country)); } finally { sqlSession.close(); } } /** * Map可以随意 */ @Test public void testDynamicDeleteMap() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Map map = new HashMap(); map.put("id", 100); Assert.assertEquals(1, mapper.deleteByPrimaryKey(map)); map = new HashMap(); map.put("countryname", "China"); Assert.assertEquals(0, mapper.deleteByPrimaryKey(map)); } finally { sqlSession.close(); } } /** * 对象不包含主键 */ @Test(expected = Exception.class) public void testDynamicDeleteNotFoundKeyProperties() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //根据主键删除 Assert.assertEquals(0, mapper.deleteByPrimaryKey(new Key())); } finally { sqlSession.close(); } } /** * 主键格式错误 */ @Test public void testDynamicDeleteException() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //根据主键删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(100)); } finally { sqlSession.rollback(); sqlSession.close(); } } class Key { } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestExistsWithPrimaryKey.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * 通过主键查询 * * @author liuzh */ public class TestExistsWithPrimaryKey { /** * 根据PK进行查询 */ @Test public void testDynamicExistsWithPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(35); Assert.assertEquals(true, mapper.existsWithPrimaryKey(country)); country.setId(0); Assert.assertEquals(false, mapper.existsWithPrimaryKey(country)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestInsert.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.List; /** * 通过实体类属性进行插入 * * @author liuzh */ public class TestInsert { /** * 插入空数据,id不能为null,会报错 */ @Test(expected = PersistenceException.class) public void testDynamicInsertAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.insert(new Country()); } finally { sqlSession.close(); } } /** * 不能插入null */ @Test(expected = PersistenceException.class) public void testDynamicInsertAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.insert(null); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testDynamicInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insert(country)); //查询CN结果2个 country = new Country(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(2, list.size()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } /** * 插入code为null的数据,不会使用默认值HH */ @Test public void testDynamicInsertNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(10086); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insert(country)); //查询CN结果2个 country = new Country(); country.setId(10086); List list = mapper.select(country); Assert.assertEquals(1, list.size()); Assert.assertNull(list.get(0).getCountrycode()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestInsertSelective.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.List; /** * 通过实体类属性进行插入不为null的数据 * * @author liuzh */ public class TestInsertSelective { /** * 插入空数据,id不能为null,会报错 */ @Test(expected = PersistenceException.class) public void testDynamicInsertAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.insertSelective(new Country()); } finally { sqlSession.close(); } } /** * 不能插入null */ @Test(expected = PersistenceException.class) public void testDynamicInsertSelectiveAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.insertSelective(null); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testDynamicInsertSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insertSelective(country)); //查询CN结果2个 country = new Country(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(2, list.size()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } /** * Countrycode默认值HH */ @Test public void testDynamicInsertSelectiveNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(10086); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insertSelective(country)); //查询CN结果2个 country = new Country(); country.setId(10086); List list = mapper.select(country); Assert.assertEquals(1, list.size()); //默认值 Assert.assertNotNull(list.get(0).getCountrycode()); Assert.assertEquals("HH", list.get(0).getCountrycode()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestSelect.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.List; /** * 通过实体类属性进行查询 * * @author liuzh */ public class TestSelect { /** * 查询全部 */ @Test public void testDynamicSelectAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); List countryList; //country.setDynamicTableName123("country_123"); //countryList = mapper.select(country); //查询总数 //Assert.assertEquals(2, countryList.size()); country.setDynamicTableName123(null); countryList = mapper.select(country); //查询总数 Assert.assertEquals(183, countryList.size()); } finally { sqlSession.close(); } } /** * 查询全部 */ @Test public void testDynamicSelectPage() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("US"); List countryList = mapper.selectPage(country, 0, 10); //查询总数 Assert.assertEquals(1, countryList.size()); countryList = mapper.selectPage(null, 100, 10); //查询总数 Assert.assertEquals(10, countryList.size()); } finally { sqlSession.close(); } } /** * 查询全部 */ @Test public void testAllColumns() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); //35,'China','CN' country.setCountrycode("CN"); country.setId(35); country.setCountryname("China"); List countryList = mapper.select(country); Assert.assertEquals(1, countryList.size()); } finally { sqlSession.close(); } } /** * 入参为null时查询全部 */ @Test public void testDynamicSelectAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.select(null); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); List countryList = mapper.select(country); Assert.assertEquals(1, countryList.size()); Assert.assertEquals(true, countryList.get(0).getId() == 35); Assert.assertEquals("China", countryList.get(0).getCountryname()); } finally { sqlSession.close(); } } /** * 查询不存在的结果 */ @Test public void testDynamicSelectZero() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); country.setCountryname("天朝");//实际上是 China List countryList = mapper.select(country); Assert.assertEquals(0, countryList.size()); } finally { sqlSession.close(); } } /** * 继承类可以使用,但多出来的属性无效 */ @Test public void testDynamicSelectNotFoundKeyProperties() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //根据主键删除 Assert.assertEquals(183, mapper.select(new Key()).size()); Key key = new Key(); key.setCountrycode("CN"); key.setCountrytel("+86"); Assert.assertEquals(1, mapper.select(key).size()); } finally { sqlSession.close(); } } class Key extends Country { private String countrytel; public String getCountrytel() { return countrytel; } public void setCountrytel(String countrytel) { this.countrytel = countrytel; } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestSelectAll.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.List; /** * 通过实体类属性进行查询 * * @author liuzh */ public class TestSelectAll { /** * 查询全部 */ @Test public void testDynamicSelectPage() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List countryList = mapper.selectAll(); //查询总数 Assert.assertEquals(183, countryList.size()); } finally { sqlSession.close(); } } /** * 查询全部 */ @Test public void testDynamicSelectPage2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List countryList = mapper.selectAll(); //查询总数 Assert.assertEquals(183, countryList.size()); //selectAll有排序 Assert.assertEquals(183, (int) countryList.get(0).getId()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestSelectByPrimaryKey.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.HashMap; import java.util.Map; /** * 通过主键查询 * * @author liuzh */ public class TestSelectByPrimaryKey { /** * 根据PK进行查询 */ @Test public void testDynamicSelectByPrimaryKey2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = mapper.selectByPrimaryKey(35); Assert.assertNotNull(country); Assert.assertEquals(true, country.getId() == 35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); } finally { sqlSession.close(); } } /** * 包含主键的对象做参数就行 */ @Test public void testDynamicSelectByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(35); country = mapper.selectByPrimaryKey(country); Assert.assertNotNull(country); Assert.assertEquals(true, country.getId() == 35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); } finally { sqlSession.close(); } } /** * 查询不存在的结果 */ @Test public void testDynamicSelectByPrimaryKeyZero() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertNull(mapper.selectByPrimaryKey(new Country())); Assert.assertNull(mapper.selectByPrimaryKey(new HashMap())); Assert.assertNull(mapper.selectByPrimaryKey(-10)); Assert.assertNull(mapper.selectByPrimaryKey(0)); Assert.assertNull(mapper.selectByPrimaryKey(1000)); Assert.assertNull(mapper.selectByPrimaryKey(null)); } finally { sqlSession.close(); } } /** * Map可以随意 */ @Test public void testSelectByPrimaryKeyMap() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Map map = new HashMap(); map.put("id", 35); Country country = mapper.selectByPrimaryKey(map); Assert.assertNotNull(country); Assert.assertEquals(true, country.getId() == 35); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); map = new HashMap(); map.put("countryname", "China"); Assert.assertNull(mapper.selectByPrimaryKey(map)); } finally { sqlSession.close(); } } /** * 对象不包含主键 */ @Test(expected = Exception.class) public void testDynamicDeleteNotFoundKeyProperties() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.selectByPrimaryKey(new Key()); } finally { sqlSession.close(); } } /** * 主键格式错误 */ @Test public void testDynamicDeleteException() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.selectByPrimaryKey(100); } finally { sqlSession.close(); } } class Key { } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestSelectCount.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * 通过实体类属性查询总数 * * @author liuzh */ public class TestSelectCount { /** * 查询全部 */ @Test public void testDynamicSelectCount() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //查询总数 Assert.assertEquals(183, mapper.selectCount(new Country())); } finally { sqlSession.close(); } } /** * 入参为null时查询全部 */ @Test public void testDynamicSelectAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //查询总数 Assert.assertEquals(183, mapper.selectCount(null)); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); Assert.assertEquals(1, mapper.selectCount(country)); } finally { sqlSession.close(); } } /** * 查询不存在的结果 */ @Test public void testDynamicSelectZero() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); country.setCountryname("天朝");//实际上是 China Assert.assertEquals(0, mapper.selectCount(country)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestSelectOne.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.exceptions.TooManyResultsException; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * 通过实体类属性进行查询 * * @author liuzh */ public class TestSelectOne { /** * 查询全部 */ @Test(expected = TooManyResultsException.class) public void testDynamicSelectAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = mapper.selectOne(new Country()); } finally { sqlSession.close(); } } /** * 入参为null时查询全部 */ @Test(expected = TooManyResultsException.class) public void testDynamicSelectAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.selectOne(null); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); Country result = mapper.selectOne(country); Assert.assertEquals(true, result.getId() == 35); Assert.assertEquals("China", result.getCountryname()); } finally { sqlSession.close(); } } /** * 查询不存在的结果 */ @Test public void testDynamicSelectZero() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); country.setCountryname("天朝");//实际上是 China Country result = mapper.selectOne(country); Assert.assertNull(result); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestUpdateByPrimaryKey.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.CountryVersionMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import tk.mybatis.mapper.model.CountryVersion; /** * 通过PK更新实体类全部属性 * * @author liuzh */ public class TestUpdateByPrimaryKey { /** * 更新0个 */ @Test public void testDynamicUpdateByPrimaryKeyAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertEquals(0, mapper.updateByPrimaryKey(new Country())); } finally { sqlSession.close(); } } /** * 入参为null时更新全部 */ @Test public void testDynamicUpdateByPrimaryKeyAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.updateByPrimaryKey(null); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(174); country.setCountryname(null); country.setCountryname("美国"); Assert.assertEquals(1, mapper.updateByPrimaryKey(country)); country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country); Assert.assertEquals(174, (int) country.getId()); Assert.assertEquals("美国", country.getCountryname()); Assert.assertNull(country.getCountrycode()); } finally { sqlSession.close(); } } /** * 继承类可以使用,但多出来的属性无效 */ @Test public void testDynamicUpdateByPrimaryKeyNotFoundKeyProperties() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertEquals(0, mapper.updateByPrimaryKey(new Key())); Key key = new Key(); key.setId(174); key.setCountrycode("CN"); key.setCountrytel("+86"); Assert.assertEquals(1, mapper.updateByPrimaryKey(key)); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testUpdateByPrimaryKeyAndVersion() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryVersionMapper mapper = sqlSession.getMapper(CountryVersionMapper.class); CountryVersion country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country); Assert.assertEquals(new Integer(1), country.getVersion()); country.setCountryname("美国2"); Assert.assertEquals(1, mapper.updateByPrimaryKey(country)); country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country); Assert.assertEquals(new Integer(2), country.getVersion()); country.setCountryname("美国3"); Assert.assertEquals(1, mapper.updateByPrimaryKey(country)); country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country); Assert.assertEquals(new Integer(3), country.getVersion()); country.setCountryname("美国4"); Assert.assertEquals(1, mapper.updateByPrimaryKey(country)); country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country); Assert.assertEquals(new Integer(4), country.getVersion()); } finally { sqlSession.close(); } } class Key extends Country { private String countrytel; public String getCountrytel() { return countrytel; } public void setCountrytel(String countrytel) { this.countrytel = countrytel; } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country/TestUpdateByPrimaryKeySelective.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * 通过PK更新实体类非null属性 * * @author liuzh */ public class TestUpdateByPrimaryKeySelective { @Test(expected = PersistenceException.class) public void testDynamicUpdateByPrimaryKeySelectiveAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertEquals(0, mapper.updateByPrimaryKeySelective(new Country())); } finally { sqlSession.close(); } } @Test(expected = PersistenceException.class) public void testDynamicUpdateByPrimaryKeySelectiveAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertEquals(0, mapper.updateByPrimaryKeySelective(null)); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicUpdateByPrimaryKeySelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setId(173); country.setCountryname("英国"); Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(country)); country = mapper.selectByPrimaryKey(173); Assert.assertNotNull(country); Assert.assertEquals(173, (int) country.getId()); Assert.assertEquals("英国", country.getCountryname()); Assert.assertNotNull(country.getCountrycode()); Assert.assertEquals("GB", country.getCountrycode()); } finally { sqlSession.close(); } } /** * 继承类可以使用,但多出来的属性无效 */ @Test public void testDynamicUpdateByPrimaryKeySelectiveNotFoundKeyProperties() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Key key = new Key(); key.setId(173); key.setCountrycode("CN"); key.setCountrytel("+86"); Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(key)); } finally { sqlSession.close(); } } class Key extends Country { private String countrytel; public String getCountrytel() { return countrytel; } public void setCountrytel(String countrytel) { this.countrytel = countrytel; } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country2/TestInsert.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country2; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.Country2Mapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country2; import java.util.List; /** * 通过实体类属性进行插入 - Country2 自动增长ID * * @author liuzh */ public class TestInsert { /** * 插入空数据,id不能为null,会报错 */ @Test public void testDynamicInsertAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); Country2 country2 = new Country2(); country2.setCountrycode("CN"); country2.setId(100); Assert.assertEquals(1, mapper.insert(country2)); country2 = mapper.select(country2).get(0); Assert.assertNotNull(country2); Assert.assertEquals(1, mapper.deleteByPrimaryKey(country2.getId())); } finally { sqlSession.close(); } } /** * 不能插入null */ @Test public void testDynamicInsertAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); mapper.insert(null); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testDynamicInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); Country2 country = new Country2(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insert(country)); //查询CN结果2个 country = new Country2(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(1, list.size()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } /** * 插入code为null的数据,不会使用默认值HH */ @Test public void testDynamicInsertNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); Country2 country = new Country2(); country.setId(10086); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insert(country)); //查询CN结果2个 country = new Country2(); country.setId(10086); List list = mapper.select(country); Assert.assertEquals(1, list.size()); Assert.assertNull(list.get(0).getCountrycode()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/country2/TestInsertSelective.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.country2; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.Country2Mapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country2; import java.util.List; /** * 通过实体类属性进行插入不为null的数据 * * @author liuzh */ public class TestInsertSelective { /** * 插入空数据,id不能为null,会报错 */ @Test public void testDynamicInsertAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); Country2 country2 = new Country2(); country2.setCountrycode("CN"); Assert.assertEquals(1, mapper.insertSelective(country2)); country2 = mapper.select(country2).get(0); Assert.assertNotNull(country2); Assert.assertEquals(1, mapper.deleteByPrimaryKey(country2.getId())); } finally { sqlSession.close(); } } /** * 不能插入null */ @Test//(expected = PersistenceException.class) public void testDynamicInsertSelectiveAllByNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); mapper.insertSelective(null); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testDynamicInsertSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); Country2 country = new Country2(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insertSelective(country)); //查询CN结果2个 country = new Country2(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(1, list.size()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } /** * Country2code默认值HH */ @Test public void testDynamicInsertSelectiveNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country2Mapper mapper = sqlSession.getMapper(Country2Mapper.class); Country2 country = new Country2(); country.setId(10086); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insertSelective(country)); //查询CN结果2个 country = new Country2(); country.setId(10086); List list = mapper.select(country); Assert.assertEquals(1, list.size()); //默认值 Assert.assertNotNull(list.get(0).getCountrycode()); Assert.assertEquals("HH", list.get(0).getCountrycode()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestDeleteByExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.example; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.model.CountryExample; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * @author liuzh */ public class TestDeleteByExample { @Test public void testDeleteByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100); int count = mapper.deleteByExample(example); //查询总数 Assert.assertEquals(83, count); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testDeleteByExample2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andLike("countryname", "A%"); example.or().andGreaterThan("id", 100); example.setDistinct(true); int count = mapper.deleteByExample(example); //查询总数 Assert.assertEquals(true, count > 83); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testDeleteByExample3() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); CountryExample example = new CountryExample(); example.createCriteria().andCountrynameLike("A%"); example.or().andIdGreaterThan(100); example.setDistinct(true); int count = mapper.deleteByExample(example); //查询总数 Assert.assertEquals(true, count > 83); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestExampleBuilder.java ================================================ package tk.mybatis.mapper.test.example; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import tk.mybatis.mapper.util.Sqls; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author wuyi * @date 2017/11/18 */ public class TestExampleBuilder { @Test public void testExampleBuilder() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class).build(); List countries = mapper.selectByExample(example); Assert.assertEquals(183, countries.size()); // 下面的查询会有缓存 Example example0 = Example.builder(Country.class) .select().build(); List countries0 = mapper.selectByExample(example0); Assert.assertEquals(183, countries0.size()); } finally { sqlSession.close(); } } @Test public void testDistinct() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .distinct() .build(); List countries = mapper.selectByExample(example); Assert.assertEquals(183, countries.size()); // distinct和order by冲突问题 Example example0 = Example.builder(Country.class) .selectDistinct("id", "countryname").build(); List countries0 = mapper.selectByExample(example0); Assert.assertEquals(183, countries0.size()); } finally { sqlSession.close(); } } @Test public void testForUpdate() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .select("countryname") .where(Sqls.custom().andGreaterThan("id", 100)) .orderByAsc("countrycode") .forUpdate() .build(); List countries = mapper.selectByExample(example); Assert.assertEquals(83, countries.size()); } finally { sqlSession.close(); } } @Test public void testEqualTo() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom().andEqualTo("id", "35")) .build(); List countries = mapper.selectByExample(example); Country country = countries.get(0); Assert.assertEquals(Integer.valueOf(35), country.getId()); Assert.assertEquals("China", country.getCountryname()); Assert.assertEquals("CN", country.getCountrycode()); } finally { sqlSession.close(); } } @Test public void testBetween() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom().andBetween("id", 34, 35)) .build(); List countries = mapper.selectByExample(example); Country country35 = countries.get(0); Assert.assertEquals(Integer.valueOf(35), country35.getId()); Assert.assertEquals("China", country35.getCountryname()); Assert.assertEquals("CN", country35.getCountrycode()); Country country34 = countries.get(1); Assert.assertEquals(Integer.valueOf(34), country34.getId()); Assert.assertEquals("Chile", country34.getCountryname()); Assert.assertEquals("CL", country34.getCountrycode()); } finally { sqlSession.close(); } } @Test public void testIn() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom().andIn("id", new ArrayList(Arrays.asList(35, 183)))) .build(); List countries = mapper.selectByExample(example); Country country35 = countries.get(1); Assert.assertEquals(Integer.valueOf(35), country35.getId()); Assert.assertEquals("China", country35.getCountryname()); Assert.assertEquals("CN", country35.getCountrycode()); Country country183 = countries.get(0); Assert.assertEquals(Integer.valueOf(183), country183.getId()); Assert.assertEquals("Zambia", country183.getCountryname()); Assert.assertEquals("ZM", country183.getCountrycode()); } finally { sqlSession.close(); } } /* * @description: 单个where组合查询测试 * 直接把example的构造放到selectByExample()函数里 * */ @Test public void testWhereCompound0() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List countries = mapper.selectByExample( Example.builder(Country.class) .where(Sqls.custom() .andEqualTo("countryname", "China") .andEqualTo("id", 35) .orIn("id", new ArrayList(Arrays.asList(35, 183))) .orLike("countryname", "Ye%") ) .build()); Country country35 = countries.get(2); Assert.assertEquals(Integer.valueOf(35), country35.getId()); Assert.assertEquals("China", country35.getCountryname()); Assert.assertEquals("CN", country35.getCountrycode()); Country country183 = countries.get(0); Assert.assertEquals(Integer.valueOf(183), country183.getId()); Assert.assertEquals("Zambia", country183.getCountryname()); Assert.assertEquals("ZM", country183.getCountrycode()); Country country179 = countries.get(1); Assert.assertEquals(Integer.valueOf(179), country179.getId()); Assert.assertEquals("Yemen", country179.getCountryname()); Assert.assertEquals("YE", country179.getCountrycode()); } finally { sqlSession.close(); } } /* * @description: 单个where组合查询测试 * */ @Test public void testWhereCompound1() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom() .andBetween("id", 35, 50) .orLessThan("id", 40) .orIsNull("countryname") ) .build(); List countries = mapper.selectByExample(example); Assert.assertEquals(50, countries.size()); } finally { sqlSession.close(); } } /* * @description: 多个where连接的查询语句测试 * */ @Test public void testWhereAndWhereCompound() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom() .andEqualTo("countryname", "China") .andEqualTo("id", 35) ) .andWhere(Sqls.custom() .andEqualTo("id", 183) ) .build(); List countries = mapper.selectByExample(example); Assert.assertEquals(0, countries.size()); } finally { sqlSession.close(); } } /* * @description: 多个where连接的查询语句测试 * */ @Test public void testWhereOrWhereCompound() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom() .andEqualTo("countryname", "China") .andEqualTo("id", 35) ) .orWhere(Sqls.custom() .andEqualTo("id", 183) ) .build(); List countries = mapper.selectByExample(example); Assert.assertEquals(2, countries.size()); } finally { sqlSession.close(); } } /* * @description: 多个where连接的查询语句测试 * */ @Test public void testMultiWhereCompound() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .selectDistinct() .where(Sqls.custom() .andEqualTo("countryname", "China") .andEqualTo("id", 35) ) .orWhere(Sqls.custom() .andBetween("countryname", 'C', 'H') .andNotLike("countryname", "Co%") ) .andWhere(Sqls.custom() .andLessThan("id", "100") .orGreaterThan("id", "55") ) .orWhere(Sqls.custom() .andEqualTo("countryname", "Cook Is.") ) .orderByAsc("id", "countryname") .orderByDesc("countrycode") .forUpdate() .build(); List countries = mapper.selectByExample(example); Assert.assertEquals(35, countries.size()); } finally { sqlSession.close(); } } /* * @description: 测试order by * orderBy()默认为Asc(升序),与orderByAsc()一样 * */ @Test public void testOrderBy() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = Example.builder(Country.class) .where(Sqls.custom().andBetween("id", 50, 55)) .orderBy("id").orderByAsc("countryname").orderByDesc("countrycode") .build(); List countries = mapper.selectByExample(example); for (Country country : countries) { System.out.println(country.getId() + " " + country.getCountryname() + " " + country.getCountrycode()); } Assert.assertEquals(6, countries.size()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestSelectByExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.example; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.model.CountryExample; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import tk.mybatis.mapper.model.Country2; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @author liuzh */ public class TestSelectByExample { @Rule public ExpectedException exception = ExpectedException.none(); @Test public void testSelectByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(90, countries.size()); } finally { sqlSession.close(); } } @Test(expected = Exception.class) public void testSelectByExampleException() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country2.class); example.createCriteria().andGreaterThan("id", 100); mapper.selectByExample(example); } finally { sqlSession.close(); } } @Test public void testSelectByExampleForUpdate() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.setForUpdate(true); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(90, countries.size()); } finally { sqlSession.close(); } } @Test public void testAndExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria() .andCondition("countryname like 'C%' and id < 100") .andCondition("length(countryname) = ", 5); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(3, countries.size()); } finally { sqlSession.close(); } } @Test public void testSelectByExampleInNotIn() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); Set set = new HashSet(); set.addAll(Arrays.asList(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11})); example.createCriteria().andIn("id", set) .andNotIn("id", Arrays.asList(new Object[]{11})); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(10, countries.size()); } finally { sqlSession.close(); } } @Test public void testSelectByExampleInNotIn2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andIn("id", Arrays.asList(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11})) .andNotIn("id", Arrays.asList(new Object[]{11})); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(10, countries.size()); } finally { sqlSession.close(); } } @Test public void testSelectByExample2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andLike("countryname", "A%"); example.or().andGreaterThan("id", 100); example.setDistinct(true); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(true, countries.size() > 83); } finally { sqlSession.close(); } } @Test public void testSelectByExample3() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); CountryExample example = new CountryExample(); example.createCriteria().andCountrynameLike("A%"); example.or().andIdGreaterThan(100); example.setDistinct(true); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(true, countries.size() > 83); } finally { sqlSession.close(); } } @Test public void testSelectByExample4() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { Country ct = new Country(); ct.setCountryname("China"); CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 20).andEqualTo(ct); List countries = mapper.selectByExample(example); //查询总数 System.out.println(countries.get(0).toString()); Assert.assertEquals(1, countries.size()); } finally { sqlSession.close(); } } @Test public void testSelectColumnsByExample() { exception.expect(MapperException.class); exception.expectMessage("类 Country 不包含属性 'hehe',或该属性被@Transient注释!"); SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); example.selectProperties("id", "countryname", "hehe"); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(90, countries.size()); } finally { sqlSession.close(); } } @Test public void testExcludeColumnsByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); example.excludeProperties("id"); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(90, countries.size()); } finally { sqlSession.close(); } } @Test public void testAndOr() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(90, countries.size()); //当不使用条件时,也不能出错 example = new Example(Country.class); example.createCriteria(); example.or(); example.and(); countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(183, countries.size()); } finally { sqlSession.close(); } } @Test public void testOrderBy() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); // example.setOrderByClause("id desc"); example.orderBy("id").desc().orderBy("countryname").orderBy("countrycode").asc(); List countries = mapper.selectByExample(example); //查询总数 Assert.assertEquals(183, (int) countries.get(0).getId()); } finally { sqlSession.close(); } } /** * 指定查询字段正确 */ @Test public void testSelectPropertisCheckCorrect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.selectProperties(new String[]{"countryname"}); example.createCriteria().andEqualTo("id", 35); List country1 = mapper.selectByExample(example); Assert.assertEquals(null, country1.get(0).getId()); Assert.assertEquals("China", country1.get(0).getCountryname()); Assert.assertEquals(null, country1.get(0).getCountrycode()); } finally { sqlSession.close(); } } /** * 指定查询字段拼写错误或不存在 */ @Test public void testSelectPropertisCheckSpellWrong() { exception.expect(MapperException.class); exception.expectMessage("类 Country 不包含属性 'countrymame',或该属性被@Transient注释!"); SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.selectProperties(new String[]{"countrymame"}); example.createCriteria().andEqualTo("id", 35); List country2 = mapper.selectByExample(example); Assert.assertEquals(null, country2.get(0).getId()); Assert.assertEquals("China", country2.get(0).getCountryname()); Assert.assertEquals(null, country2.get(0).getCountrycode()); } finally { sqlSession.close(); } } /** * 指定查询字段为@Transient注释字段 */ @Test public void testSelectPropertisCheckTransient1() { exception.expect(MapperException.class); exception.expectMessage("类 Country 不包含属性 'name',或该属性被@Transient注释!"); SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.selectProperties(new String[]{"name"}); example.createCriteria().andEqualTo("id", 35); List country = mapper.selectByExample(example); } finally { sqlSession.close(); } } /** * 指定查询字段为@Transient注释字段 */ @Test public void testSelectPropertisCheckTransient2() { exception.expect(MapperException.class); exception.expectMessage("类 Country 不包含属性 'dynamicTableName123',或该属性被@Transient注释!"); SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.selectProperties(new String[]{"dynamicTableName123"}); example.createCriteria().andEqualTo("id", 35); List country = mapper.selectByExample(example); } finally { sqlSession.close(); } } /** * 指定排除的查询字段不存在或拼写错误 */ @Test public void testExcludePropertisCheckWrongSpell() { exception.expect(MapperException.class); exception.expectMessage("类 Country 不包含属性 'countrymame',或该属性被@Transient注释!"); SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.excludeProperties(new String[]{"countrymame"}); example.createCriteria().andEqualTo("id", 35); List country = mapper.selectByExample(example); } finally { sqlSession.close(); } } /** * 指定排除的查询字段为@Transient注释字段 */ @Test public void testExcludePropertisCheckTransient() { exception.expect(MapperException.class); exception.expectMessage("类 Country 不包含属性 'dynamicTableName123',或该属性被@Transient注释!"); SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.excludeProperties(new String[]{"dynamicTableName123"}); example.createCriteria().andEqualTo("id", 35); List country = mapper.selectByExample(example); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestSelectCountByExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.example; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.model.CountryExample; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * @author liuzh */ public class TestSelectCountByExample { @Test public void testSelectCountByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.setCountProperty("id"); example.createCriteria().andGreaterThan("id", 100); int count = mapper.selectCountByExample(example); //查询总数 Assert.assertEquals(83, count); } finally { sqlSession.close(); } } @Test public void testSelectCountByExampleForUpdate() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.setForUpdate(true); example.createCriteria().andGreaterThan("id", 100); int count = mapper.selectCountByExample(example); //查询总数 Assert.assertEquals(83, count); } finally { sqlSession.close(); } } @Test public void testSelectCountByExample2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andLike("countryname", "A%"); example.or().andGreaterThan("id", 100); example.setDistinct(true); int count = mapper.selectCountByExample(example); //查询总数 Assert.assertEquals(true, count > 83); } finally { sqlSession.close(); } } @Test public void testSelectCountByExample3() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); CountryExample example = new CountryExample(); example.createCriteria().andCountrynameLike("A%"); example.or().andIdGreaterThan(100); example.setDistinct(true); int count = mapper.selectCountByExample(example); //查询总数 Assert.assertEquals(true, count > 83); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestSelectOneByExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.example; import org.apache.ibatis.exceptions.TooManyResultsException; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * @author liuzh */ public class TestSelectOneByExample { @Test(expected = TooManyResultsException.class) public void testSelectOneByExampleException() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); mapper.selectOneByExample(example); } finally { sqlSession.close(); } } @Test public void testSelectByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 102); Country country = mapper.selectOneByExample(example); Assert.assertNotNull(country); Assert.assertEquals(new Integer(101), country.getId()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestUpdateByExample.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.example; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.model.CountryExample; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * 由于主键的原因,这里实际只能更新一个,在没有主键的表中,可以更新多个 * * @author liuzh */ public class TestUpdateByExample { @Test public void testUpdateByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andEqualTo("id", 35); Country country = new Country(); //country.setDynamicTableName123("country_123"); country.setCountryname("天朝"); country.setId(1000); int count = mapper.updateByExample(country, example); Assert.assertEquals(1, count); example = new Example(Country.class); example.createCriteria().andIsNull("countrycode"); count = mapper.selectCountByExample(example); Assert.assertEquals(1, count); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdateByExample2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountryname("天朝"); country.setId(1000); CountryExample example = new CountryExample(); example.createCriteria().andIdEqualTo(35); int count = mapper.updateByExample(country, example); Assert.assertEquals(1, count); example = new CountryExample(); example.createCriteria().andCountrycodeIsNull(); count = mapper.selectCountByExample(example); Assert.assertEquals(1, count); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/example/TestUpdateByExampleSelective.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.example; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.model.CountryExample; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; /** * @author liuzh */ public class TestUpdateByExampleSelective { @Test public void testUpdateByExampleSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100); Country country = new Country(); country.setCountryname("天朝"); int count = mapper.updateByExampleSelective(country, example); Assert.assertEquals(83, count); example = new Example(Country.class); example.createCriteria().andEqualTo("countryname", "天朝"); count = mapper.selectCountByExample(example); Assert.assertEquals(83, count); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdateByExampleSelective2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andLike("countryname", "A%"); example.or().andGreaterThan("id", 100); example.setDistinct(true); Country country = new Country(); country.setCountryname("天朝"); int count = mapper.updateByExampleSelective(country, example); Assert.assertEquals(true, count > 83); example = new Example(Country.class); example.createCriteria().andEqualTo("countryname", "天朝"); count = mapper.selectCountByExample(example); Assert.assertEquals(true, count > 83); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdateByExampleSelective3() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); CountryExample example = new CountryExample(); example.createCriteria().andCountrynameLike("A%"); example.or().andIdGreaterThan(100); example.setDistinct(true); Country country = new Country(); country.setCountryname("天朝"); int count = mapper.updateByExampleSelective(country, example); Assert.assertEquals(true, count > 83); example = new CountryExample(); example.createCriteria().andCountrynameEqualTo("天朝"); count = mapper.selectCountByExample(example); Assert.assertEquals(true, count > 83); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/identity/TestIndentity.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.identity; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryIMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.CountryI; import java.util.List; /** * Created by liuzh on 2014/11/21. */ public class TestIndentity { /** * 插入完整数据 */ @Test public void testINDENTITYInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryIMapper mapper = sqlSession.getMapper(CountryIMapper.class); CountryI country = new CountryI(); country.setCountrycode("CN"); Assert.assertEquals(1, mapper.insert(country)); //ID会回写 Assert.assertNotNull(country.getId()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(country.getId())); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testINDENTITYInsert2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryIMapper mapper = sqlSession.getMapper(CountryIMapper.class); CountryI country = new CountryI(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insert(country)); //查询CN结果 country = new CountryI(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(1, list.size()); Assert.assertNotNull(list.get(0).getCountryname()); Assert.assertEquals("天朝", list.get(0).getCountryname()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testINDENTITYInsertSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryIMapper mapper = sqlSession.getMapper(CountryIMapper.class); CountryI country = new CountryI(); Assert.assertEquals(1, mapper.insertSelective(country)); //ID会回写 Assert.assertNotNull(country.getId()); //带有默认值的其他的属性不会自动回写,需要手动查询 country = mapper.selectByPrimaryKey(country); //查询后,默认值不为null Assert.assertNotNull(country.getCountrycode()); Assert.assertEquals("HH", country.getCountrycode()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(country.getId())); } finally { sqlSession.close(); } } /** * 插入完整数据 */ @Test public void testINDENTITYInsertSelective2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryIMapper mapper = sqlSession.getMapper(CountryIMapper.class); CountryI country = new CountryI(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insertSelective(country)); //查询CN结果 country = new CountryI(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(1, list.size()); Assert.assertNotNull(list.get(0).getCountryname()); Assert.assertEquals("天朝", list.get(0).getCountryname()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/ids/TestIds.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.ids; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.List; /** * 通过 ids 进行操作 * * @author liuzh */ public class TestIds { @Test public void testSelectByIds() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List countryList = mapper.selectByIds("1,2,3"); //查询总数 Assert.assertEquals(3, countryList.size()); } finally { sqlSession.close(); } } @Test public void testDeleteByIds() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); int count = mapper.deleteByIds("1,2,3"); //查询总数 Assert.assertEquals(3, count); Assert.assertEquals(180, mapper.selectCount(null)); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/jdbc/TestJDBC.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.jdbc; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import tk.mybatis.mapper.mapper.CountryJDBCMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.CountryJDBC; /** * sqlserver测试 - 该类注释所有测试方法是因为该测试是针对sqlserver的,而项目测试用的hsqldb,所以这些测试不能运行,需要换为sqlserver才可以 */ public class TestJDBC { // @Test public void testJDBC() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryJDBCMapper mapper = sqlSession.getMapper(CountryJDBCMapper.class); CountryJDBC country = new CountryJDBC(); country.setId(1); country.setCountrycode("CN"); country.setCountryname("China"); Assert.assertEquals(1, mapper.insert(country)); Assert.assertNotNull(country.getId()); } finally { sqlSession.rollback(); sqlSession.close(); } } // @Test public void testJDBC2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryJDBCMapper mapper = sqlSession.getMapper(CountryJDBCMapper.class); CountryJDBC country = new CountryJDBC(); country.setId(1); country.setCountrycode("CN"); country.setCountryname("China"); Assert.assertEquals(1, mapper.insertSelective(country)); Assert.assertNotNull(country.getId()); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/logic/TestLogicDelete.java ================================================ package tk.mybatis.mapper.test.logic; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.TbUserLogicDeleteMapper; import tk.mybatis.mapper.mapper.TbUserMapper; import tk.mybatis.mapper.model.TbUser; import tk.mybatis.mapper.model.TbUserLogicDelete; import java.util.List; public class TestLogicDelete { @Test public void testLogicDeleteByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); logicDeleteMapper.deleteByPrimaryKey(3); Assert.assertFalse(logicDeleteMapper.existsWithPrimaryKey(3)); Assert.assertTrue(mapper.existsWithPrimaryKey(3)); // 删除已经被逻辑删除的数据,受影响行数为0 Assert.assertEquals(0, logicDeleteMapper.deleteByPrimaryKey(9)); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test // 删除实体,会带上未删除的查询条件,并忽略实体类给逻辑删除字段设置的值 public void testLogicDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); // 有2条username为test的数据,其中1条已经被标记为逻辑删除 TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); tbUserLogicDelete.setUsername("test"); Assert.assertTrue(logicDeleteMapper.existsWithPrimaryKey(8)); // 逻辑删除只会删除1条 Assert.assertEquals(1, logicDeleteMapper.delete(tbUserLogicDelete)); Assert.assertFalse(logicDeleteMapper.existsWithPrimaryKey(8)); // 未删除的一共有4条 Assert.assertEquals(4, logicDeleteMapper.selectAll().size()); TbUser tbUser = new TbUser(); tbUser.setUsername("test"); Assert.assertEquals(2, mapper.select(tbUser).size()); // 物理删除2条已经为逻辑删除状态的数据 Assert.assertEquals(2, mapper.delete(tbUser)); // 未删除的总数仍为4条 Assert.assertEquals(4, logicDeleteMapper.selectAll().size()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testLogicDeleteByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); Example example = new Example(TbUserLogicDelete.class); example.createCriteria().andEqualTo("id", 1); logicDeleteMapper.deleteByExample(example); Assert.assertFalse(logicDeleteMapper.existsWithPrimaryKey(1)); Assert.assertTrue(mapper.existsWithPrimaryKey(1)); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test // 根据主键查询,逻辑删除注解查询时会使用未删除的查询条件 public void testSelectByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); Assert.assertNull(logicDeleteMapper.selectByPrimaryKey(9)); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); Assert.assertEquals(0, (int) mapper.selectByPrimaryKey(9).getIsValid()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testExistsWithPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); Assert.assertFalse(logicDeleteMapper.existsWithPrimaryKey(9)); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); Assert.assertTrue(mapper.existsWithPrimaryKey(9)); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test // 查询所有,逻辑删除注解查询时会使用未删除的查询条件 public void testSelectAll() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); Assert.assertEquals(5, logicDeleteMapper.selectAll().size()); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); Assert.assertEquals(9, mapper.selectAll().size()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test // 查询数量,会带上未删除的查询条件,并忽略实体类给逻辑删除字段设置的值 public void selectCount() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); // 实际有5条未删除的,4条已删除的,忽略设置的0值,查询出未删除的5条 tbUserLogicDelete.setIsValid(0); Assert.assertEquals(5, logicDeleteMapper.selectCount(tbUserLogicDelete)); // 没有逻辑删除注解的,根据指定条件查询 TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); TbUser tbUser = new TbUser(); Assert.assertEquals(9, mapper.selectCount(tbUser)); tbUser.setIsValid(0); Assert.assertEquals(4, mapper.selectCount(tbUser)); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test // 根据实体查询,会带上未删除的查询条件,并忽略实体类给逻辑删除字段设置的值 public void testSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); // 实际有5条未删除的,4条已删除的,忽略设置的0值,查询出未删除的5条 tbUserLogicDelete.setIsValid(0); Assert.assertEquals(5, logicDeleteMapper.select(tbUserLogicDelete).size()); tbUserLogicDelete.setUsername("test"); Assert.assertEquals(1, logicDeleteMapper.select(tbUserLogicDelete).size()); Assert.assertEquals(8, (long) logicDeleteMapper.select(tbUserLogicDelete).get(0).getId()); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); TbUser tbUser = new TbUser(); // 没有逻辑删除的注解,根据指定条件查询 tbUser.setIsValid(0); Assert.assertEquals(4, mapper.select(tbUser).size()); tbUser.setUsername("test"); Assert.assertEquals(1, mapper.select(tbUser).size()); Assert.assertEquals(9, (long) mapper.select(tbUser).get(0).getId()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); tbUserLogicDelete.setUsername("test111"); logicDeleteMapper.insert(tbUserLogicDelete); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); TbUser tbUser = new TbUser(); tbUser.setUsername("test222"); mapper.insert(tbUser); Assert.assertEquals(1, mapper.selectCount(tbUser)); TbUserLogicDelete tbUserLogicDelete1 = new TbUserLogicDelete(); tbUserLogicDelete1.setUsername("test222"); Assert.assertEquals(0, logicDeleteMapper.selectCount(tbUserLogicDelete1)); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testInsertSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); tbUserLogicDelete.setUsername("test333"); logicDeleteMapper.insertSelective(tbUserLogicDelete); Assert.assertEquals(1, logicDeleteMapper.selectCount(tbUserLogicDelete)); TbUserLogicDelete tbUserLogicDelete1 = new TbUserLogicDelete(); tbUserLogicDelete1.setUsername("test333"); Assert.assertEquals(1, logicDeleteMapper.selectCount(tbUserLogicDelete1)); TbUserMapper mapper = sqlSession.getMapper(TbUserMapper.class); TbUser tbUser = new TbUser(); tbUser.setUsername("test333"); mapper.insertSelective(tbUser); TbUser tbUser2 = new TbUser(); tbUser2.setUsername("test333"); Assert.assertEquals(2, mapper.selectCount(tbUser2)); Assert.assertEquals(1, logicDeleteMapper.selectCount(tbUserLogicDelete1)); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdate() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserLogicDelete tbUserLogicDelete = logicDeleteMapper.selectByPrimaryKey(1); tbUserLogicDelete.setPassword(null); logicDeleteMapper.updateByPrimaryKey(tbUserLogicDelete); Assert.assertNull(logicDeleteMapper.select(tbUserLogicDelete).get(0).getPassword()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdateSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); TbUserLogicDelete tbUserLogicDelete = logicDeleteMapper.selectByPrimaryKey(1); tbUserLogicDelete.setPassword(null); logicDeleteMapper.updateByPrimaryKeySelective(tbUserLogicDelete); Assert.assertEquals("12345678", logicDeleteMapper.select(tbUserLogicDelete).get(0).getPassword()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testSelectByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); Example example = new Example(TbUserLogicDelete.class); example.createCriteria().andEqualTo("id", 9); Assert.assertEquals(0, logicDeleteMapper.selectByExample(example).size()); example.or().andEqualTo("username", "test"); Assert.assertEquals(1, logicDeleteMapper.selectByExample(example).size()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testSelectByExample2() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); // username为test的有两条 一条标记为已删除 Example example = new Example(TbUserLogicDelete.class); example.createCriteria().andEqualTo("username", "test"); Assert.assertEquals(1, logicDeleteMapper.selectByExample(example).size()); // password为dddd的已删除 username为test2的未删除 example.or().andEqualTo("password", "dddd").orEqualTo("username", "test2"); Assert.assertEquals(2, logicDeleteMapper.selectByExample(example).size()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdateByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); // username为test的有两条 一条标记为已删除 Example example = new Example(TbUserLogicDelete.class); example.createCriteria().andEqualTo("username", "test"); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); tbUserLogicDelete.setUsername("123"); logicDeleteMapper.updateByExample(tbUserLogicDelete, example); example.clear(); example.createCriteria().andEqualTo("username", "123"); List list = logicDeleteMapper.selectByExample(example); Assert.assertEquals(1, list.size()); Assert.assertNull(list.get(0).getPassword()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void testUpdateByExampleSelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); Example example = new Example(TbUserLogicDelete.class); example.createCriteria().andEqualTo("username", "test"); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); tbUserLogicDelete.setUsername("123"); logicDeleteMapper.updateByExampleSelective(tbUserLogicDelete, example); example.clear(); example.createCriteria().andEqualTo("username", "123"); List list = logicDeleteMapper.selectByExample(example); Assert.assertEquals(1, list.size()); Assert.assertEquals("gggg", list.get(0).getPassword()); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test // Example中没有条件的非正常情况,where条件应只有逻辑删除注解的未删除条件 public void testExampleWithNoCriteria() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { TbUserLogicDeleteMapper logicDeleteMapper = sqlSession.getMapper(TbUserLogicDeleteMapper.class); Example example = new Example(TbUserLogicDelete.class); TbUserLogicDelete tbUserLogicDelete = new TbUserLogicDelete(); tbUserLogicDelete.setUsername("123"); Assert.assertEquals(5, logicDeleteMapper.updateByExample(tbUserLogicDelete, example)); Assert.assertEquals(5, logicDeleteMapper.updateByExampleSelective(tbUserLogicDelete, example)); List list = logicDeleteMapper.selectByExample(example); Assert.assertEquals(5, list.size()); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/mysql/TestMysql.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.mysql; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.ArrayList; import java.util.List; /** * 通过实体类属性进行插入 * * @author liuzh */ public class TestMysql { /** * 插入完整数据 */ //该方法测试需要mysql或者h2数据库,所以这里注释掉 //@Test public void testInsertList() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List countryList = new ArrayList(); for (int i = 0; i < 10; i++) { Country country = new Country(); country.setCountrycode("CN" + i); country.setCountryname("天朝" + i); countryList.add(country); } int count = mapper.insertList(countryList); Assert.assertEquals(10, count); for (Country country : countryList) { Assert.assertNotNull(country.getId()); } } finally { sqlSession.rollback(); sqlSession.close(); } } /** * 插入完整数据 */ //该方法测试需要mysql或者h2数据库,所以这里注释掉 //@Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = new Country(); country.setCountrycode("CN"); country.setCountryname("天朝"); int count = mapper.insertUseGeneratedKeys(country); Assert.assertEquals(1, count); Assert.assertNotNull(country.getId()); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/othres/StyleTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.othres; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.util.StringUtil; /** * @author liuzh * @since 2015-10-31 09:41 */ public class StyleTest { private String[] fields = new String[]{ "hello", "hello_world", //"hello_World", "helloWorld", "hello1", "hello_1" }; @Test public void testNormal() { for (String field : fields) { Assert.assertEquals(field, StringUtil.convertByStyle(field, Style.normal)); } } @Test public void testUppercase() { for (String field : fields) { Assert.assertEquals(field.toUpperCase(), StringUtil.convertByStyle(field, Style.uppercase)); } } @Test public void testLowercase() { for (String field : fields) { Assert.assertEquals(field.toLowerCase(), StringUtil.convertByStyle(field, Style.lowercase)); } } @Test public void testCamelhump() { for (String field : fields) { System.out.println(field + " - " + StringUtil.convertByStyle(field, Style.camelhump)); } } @Test public void testCamelhumpUppercase() { for (String field : fields) { System.out.println(field + " - " + StringUtil.convertByStyle(field, Style.camelhumpAndUppercase)); } } @Test public void testCamelhumpLowercase() { for (String field : fields) { System.out.println(field + " - " + StringUtil.convertByStyle(field, Style.camelhumpAndLowercase)); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/othres/TestDelimiter.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.othres; import org.junit.Assert; import org.junit.Test; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author liuzh * @since 2017/7/13. */ public class TestDelimiter { public static final Pattern DELIMITER = Pattern.compile("^[`\\[\"]?(.*?)[`\\]\"]?$"); @Test public void test() { Matcher matcher = DELIMITER.matcher("normal"); if (matcher.find()) { Assert.assertEquals("normal", matcher.group(1)); } matcher = DELIMITER.matcher("`mysql`"); if (matcher.find()) { Assert.assertEquals("mysql", matcher.group(1)); } matcher = DELIMITER.matcher("[sqlserver]"); if (matcher.find()) { Assert.assertEquals("sqlserver", matcher.group(1)); } matcher = DELIMITER.matcher("\"oracle\""); if (matcher.find()) { Assert.assertEquals("oracle", matcher.group(1)); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/rowbounds/TestSelectRowBounds.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.rowbounds; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.mapper.CountryMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.Country; import java.util.List; /** * @author liuzh */ public class TestSelectRowBounds { @Test public void testSelectByExample() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100).andLessThan("id", 151); example.or().andLessThan("id", 41); List countries = mapper.selectByExampleAndRowBounds(example, new RowBounds(10, 20)); //查询总数 Assert.assertEquals(20, countries.size()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/transientc/TestTransient.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.transientc; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.CountryTMapper; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.model.CountryT; import java.util.List; /** * Created by liuzh on 2014/11/21. */ public class TestTransient { /** * 插入完整数据 */ @Test public void testDynamicInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryTMapper mapper = sqlSession.getMapper(CountryTMapper.class); CountryT country = new CountryT(); country.setId(10086); country.setCountrycode("CN"); country.setCountryname("天朝"); Assert.assertEquals(1, mapper.insert(country)); //查询CN结果 country = new CountryT(); country.setCountrycode("CN"); List list = mapper.select(country); Assert.assertEquals(2, list.size()); //屏蔽的数据是null Assert.assertNull(list.get(0).getCountrycode()); //删除插入的数据,以免对其他测试产生影响 Assert.assertEquals(1, mapper.deleteByPrimaryKey(10086)); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryTMapper mapper = sqlSession.getMapper(CountryTMapper.class); CountryT country = new CountryT(); country.setId(174); country.setCountryname("美国"); country.setCountrycode("US"); Assert.assertEquals(1, mapper.updateByPrimaryKey(country)); country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country); Assert.assertEquals(174, (int) country.getId()); Assert.assertEquals("美国", country.getCountryname()); Assert.assertNull(country.getCountrycode()); } finally { sqlSession.close(); } } /** * 根据查询条件进行查询 */ @Test public void testDynamicSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryTMapper mapper = sqlSession.getMapper(CountryTMapper.class); CountryT country = new CountryT(); country.setId(174); country.setCountrycode("US"); List countryList = mapper.select(country); Assert.assertEquals(1, countryList.size()); Assert.assertEquals(true, countryList.get(0).getId() == 174); Assert.assertNotNull(countryList.get(0).getCountryname()); Assert.assertNull(countryList.get(0).getCountrycode()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/user/TestBasic.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.user; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.UserInfoMapper; import tk.mybatis.mapper.model.UserInfo; import java.util.Collection; import java.util.List; /** * 测试增删改查 * * @author liuzh */ public class TestBasic { /** * 新增 */ @Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class); UserInfo userInfo = new UserInfo(); userInfo.setUsername("abel533"); userInfo.setPassword("123456"); userInfo.setUsertype("2"); userInfo.setEmail("abel533@gmail.com"); Collection collection = sqlSession.getConfiguration().getMappedStatements(); for (Object o : collection) { if (o instanceof MappedStatement) { MappedStatement ms = (MappedStatement) o; if (ms.getId().contains("UserInfoMapper.insert")) { System.out.println(ms.getId()); } } } Assert.assertEquals(1, mapper.insert(userInfo)); Assert.assertNotNull(userInfo.getId()); Assert.assertTrue((int) userInfo.getId() >= 6); Assert.assertEquals(1, mapper.deleteByPrimaryKey(userInfo)); } finally { sqlSession.rollback(); sqlSession.close(); } } /** * 主要测试删除 */ @Test public void testDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class); //查询总数 Assert.assertEquals(5, mapper.selectCount(new UserInfo())); //查询100 UserInfo userInfo = mapper.selectByPrimaryKey(1); //根据主键删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(1)); //查询总数 Assert.assertEquals(4, mapper.selectCount(new UserInfo())); //插入 Assert.assertEquals(1, mapper.insert(userInfo)); } finally { sqlSession.rollback(); sqlSession.close(); } } /** * 查询 */ @Test public void testSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class); UserInfo userInfo = new UserInfo(); userInfo.setUsertype("1"); List userInfos = mapper.select(userInfo); Assert.assertEquals(3, userInfos.size()); } finally { sqlSession.close(); } } /** * 根据主键全更新 */ @Test public void testUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class); UserInfo userInfo = mapper.selectByPrimaryKey(2); Assert.assertNotNull(userInfo); userInfo.setUsertype(null); userInfo.setEmail("abel533@gmail.com"); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKey(userInfo)); userInfo = mapper.selectByPrimaryKey(userInfo); Assert.assertNull(userInfo.getUsertype()); Assert.assertEquals("abel533@gmail.com", userInfo.getEmail()); } finally { sqlSession.rollback(); sqlSession.close(); } } /** * 根据主键更新非null */ @Test public void testUpdateByPrimaryKeySelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class); UserInfo userInfo = mapper.selectByPrimaryKey(1); Assert.assertNotNull(userInfo); userInfo.setUsertype(null); userInfo.setEmail("abel533@gmail.com"); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(userInfo)); userInfo = mapper.selectByPrimaryKey(1); Assert.assertEquals("1", userInfo.getUsertype()); Assert.assertEquals("abel533@gmail.com", userInfo.getEmail()); } finally { sqlSession.rollback(); sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/user/TestDelete.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.user; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.UserLoginMapper; import tk.mybatis.mapper.model.UserLogin; import java.util.List; /** * 通过主键删除 * * @author liuzh */ public class TestDelete { /** * 主要测试删除 */ @Test public void testDynamicDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLoginMapper mapper = sqlSession.getMapper(UserLoginMapper.class); //查询总数 Assert.assertEquals(10, mapper.selectCount(new UserLogin())); UserLogin userLogin = new UserLogin(); userLogin.setUsername("test1"); List userLoginList = mapper.select(userLogin); //批量删除 Assert.assertEquals(userLoginList.size(), mapper.delete(userLogin)); //循环插入 for (int i = 0; i < userLoginList.size(); i++) { Assert.assertEquals(1, mapper.insert(userLoginList.get(i))); Assert.assertEquals(i + 1, (int) userLoginList.get(i).getLogid()); } //查询总数 Assert.assertEquals(10, mapper.selectCount(new UserLogin())); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/user/TestMap.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.user; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.UserInfoMapMapper; import tk.mybatis.mapper.model.UserInfoMap; import java.util.List; /** * 测试增删改查 - 不在直接支持Map * * @author liuzh */ public class TestMap { /** * 新增 */ // @Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapMapper mapper = sqlSession.getMapper(UserInfoMapMapper.class); UserInfoMap userInfoMap = new UserInfoMap(); userInfoMap.setUserName("abel533"); userInfoMap.setPassword("123456"); userInfoMap.setUserType("2"); Assert.assertEquals(1, mapper.insert(userInfoMap)); Assert.assertNotNull(userInfoMap.getId()); Assert.assertEquals(6, (int) userInfoMap.getId()); Assert.assertEquals(1, mapper.deleteByPrimaryKey(userInfoMap)); } finally { sqlSession.close(); } } /** * 主要测试删除 */ // @Test public void testDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapMapper mapper = sqlSession.getMapper(UserInfoMapMapper.class); //查询总数 Assert.assertEquals(5, mapper.selectCount(new UserInfoMap())); //查询100 UserInfoMap userInfoMap = mapper.selectByPrimaryKey(1); //根据主键删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(1)); //查询总数 Assert.assertEquals(4, mapper.selectCount(new UserInfoMap())); //插入 Assert.assertEquals(1, mapper.insert(userInfoMap)); } finally { sqlSession.close(); } } /** * 查询 */ // @Test public void testSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapMapper mapper = sqlSession.getMapper(UserInfoMapMapper.class); UserInfoMap userInfoMap = new UserInfoMap(); userInfoMap.setUserType("1"); List UserInfoMaps = mapper.select(userInfoMap); Assert.assertEquals(3, UserInfoMaps.size()); } finally { sqlSession.close(); } } /** * 根据主键全更新 */ // @Test public void testUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapMapper mapper = sqlSession.getMapper(UserInfoMapMapper.class); UserInfoMap userInfoMap = mapper.selectByPrimaryKey(2); Assert.assertNotNull(userInfoMap); userInfoMap.setUserType(null); userInfoMap.setRealName("liuzh"); //不会更新user_type Assert.assertEquals(1, mapper.updateByPrimaryKey(userInfoMap)); userInfoMap = mapper.selectByPrimaryKey(userInfoMap); Assert.assertNull(userInfoMap.getUserType()); Assert.assertEquals("liuzh", userInfoMap.getRealName()); } finally { sqlSession.close(); } } /** * 根据主键更新非null */ // @Test public void testUpdateByPrimaryKeySelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserInfoMapMapper mapper = sqlSession.getMapper(UserInfoMapMapper.class); UserInfoMap userInfoMap = mapper.selectByPrimaryKey(1); Assert.assertNotNull(userInfoMap); userInfoMap.setUserType(null); userInfoMap.setRealName("liuzh"); //不会更新user_type Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(userInfoMap)); userInfoMap = mapper.selectByPrimaryKey(1); Assert.assertEquals("1", userInfoMap.getUserType()); Assert.assertEquals("liuzh", userInfoMap.getRealName()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/user/TestUserLogin.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.user; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.UserLoginMapper; import tk.mybatis.mapper.model.UserLogin; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 通过主键删除 * * @author liuzh */ public class TestUserLogin { /** * 新增 */ @Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLoginMapper mapper = sqlSession.getMapper(UserLoginMapper.class); UserLogin userLogin = new UserLogin(); userLogin.setUsername("abel533"); userLogin.setLogindate(new Date()); userLogin.setLoginip("192.168.123.1"); Assert.assertEquals(1, mapper.insert(userLogin)); Assert.assertNotNull(userLogin.getLogid()); Assert.assertTrue(userLogin.getLogid() > 10); //这里测了实体类入参的删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(userLogin)); } finally { sqlSession.close(); } } /** * 主要测试删除 */ @Test public void testDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLoginMapper mapper = sqlSession.getMapper(UserLoginMapper.class); //查询总数 Assert.assertEquals(10, mapper.selectCount(new UserLogin())); //根据主键查询 Map key = new HashMap(); key.put("logid", 1); key.put("username", "test1"); UserLogin userLogin = mapper.selectByPrimaryKey(key); //根据主键删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(key)); //查询总数 Assert.assertEquals(9, mapper.selectCount(new UserLogin())); //插入 Assert.assertEquals(1, mapper.insert(userLogin)); } finally { sqlSession.close(); } } /** * 查询 */ @Test public void testSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLoginMapper mapper = sqlSession.getMapper(UserLoginMapper.class); UserLogin userLogin = new UserLogin(); userLogin.setUsername("test1"); List userLogins = mapper.select(userLogin); Assert.assertEquals(5, userLogins.size()); } finally { sqlSession.close(); } } /** * 根据主键全更新 */ @Test public void testUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLoginMapper mapper = sqlSession.getMapper(UserLoginMapper.class); Map key = new HashMap(); key.put("logid", 2); key.put("username", "test1"); UserLogin userLogin = mapper.selectByPrimaryKey(key); Assert.assertNotNull(userLogin); userLogin.setLoginip("1.1.1.1"); userLogin.setLogindate(null); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKey(userLogin)); userLogin = mapper.selectByPrimaryKey(userLogin); Assert.assertNull(userLogin.getLogindate()); Assert.assertEquals("1.1.1.1", userLogin.getLoginip()); } finally { sqlSession.close(); } } /** * 根据主键更新非null */ @Test public void testUpdateByPrimaryKeySelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLoginMapper mapper = sqlSession.getMapper(UserLoginMapper.class); Map key = new HashMap(); key.put("logid", 1); key.put("username", "test1"); UserLogin userLogin = mapper.selectByPrimaryKey(key); Assert.assertNotNull(userLogin); userLogin.setLogindate(null); userLogin.setLoginip("1.1.1.1"); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(userLogin)); userLogin = mapper.selectByPrimaryKey(key); Assert.assertNotNull(userLogin.getLogindate()); Assert.assertEquals("1.1.1.1", userLogin.getLoginip()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/test/user/TestUserLogin2.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.test.user; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.mapper.MybatisHelper; import tk.mybatis.mapper.mapper.UserLogin2Mapper; import tk.mybatis.mapper.model.UserLogin2; import tk.mybatis.mapper.model.UserLogin2Key; import java.util.Date; import java.util.List; /** * 通过主键删除 * * @author liuzh */ public class TestUserLogin2 { /** * 新增 */ @Test public void testInsert() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLogin2Mapper mapper = sqlSession.getMapper(UserLogin2Mapper.class); UserLogin2 userLogin = new UserLogin2(); userLogin.setUsername("abel533"); userLogin.setLogindate(new Date()); userLogin.setLoginip("192.168.123.1"); Assert.assertEquals(1, mapper.insert(userLogin)); Assert.assertNotNull(userLogin.getLogid()); Assert.assertTrue(userLogin.getLogid() > 10); //这里测了实体类入参的删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(userLogin)); } finally { sqlSession.close(); } } /** * 主要测试删除 */ @Test public void testDelete() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLogin2Mapper mapper = sqlSession.getMapper(UserLogin2Mapper.class); //查询总数 Assert.assertEquals(10, mapper.selectCount(new UserLogin2())); //根据主键查询 UserLogin2Key key = new UserLogin2(); key.setLogid(1); key.setUsername("test1"); UserLogin2 userLogin = mapper.selectByPrimaryKey(key); //根据主键删除 Assert.assertEquals(1, mapper.deleteByPrimaryKey(key)); //查询总数 Assert.assertEquals(9, mapper.selectCount(new UserLogin2())); //插入 Assert.assertEquals(1, mapper.insert(userLogin)); } finally { sqlSession.close(); } } /** * 查询 */ @Test public void testSelect() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLogin2Mapper mapper = sqlSession.getMapper(UserLogin2Mapper.class); UserLogin2 userLogin = new UserLogin2(); userLogin.setUsername("test1"); List userLogins = mapper.select(userLogin); Assert.assertEquals(5, userLogins.size()); } finally { sqlSession.close(); } } /** * 根据主键全更新 */ @Test public void testUpdateByPrimaryKey() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLogin2Mapper mapper = sqlSession.getMapper(UserLogin2Mapper.class); UserLogin2Key key = new UserLogin2(); key.setLogid(2); key.setUsername("test1"); UserLogin2 userLogin = mapper.selectByPrimaryKey(key); Assert.assertNotNull(userLogin); userLogin.setLoginip("1.1.1.1"); userLogin.setLogindate(null); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKey(userLogin)); userLogin = mapper.selectByPrimaryKey(userLogin); Assert.assertNull(userLogin.getLogindate()); Assert.assertEquals("1.1.1.1", userLogin.getLoginip()); } finally { sqlSession.close(); } } /** * 根据主键更新非null */ @Test public void testUpdateByPrimaryKeySelective() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { UserLogin2Mapper mapper = sqlSession.getMapper(UserLogin2Mapper.class); UserLogin2Key key = new UserLogin2(); key.setLogid(1); key.setUsername("test1"); UserLogin2 userLogin = mapper.selectByPrimaryKey(key); Assert.assertNotNull(userLogin); userLogin.setLogindate(null); userLogin.setLoginip("1.1.1.1"); //不会更新username Assert.assertEquals(1, mapper.updateByPrimaryKeySelective(userLogin)); userLogin = mapper.selectByPrimaryKey(key); Assert.assertNotNull(userLogin.getLogindate()); Assert.assertEquals("1.1.1.1", userLogin.getLoginip()); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/Address.java ================================================ package tk.mybatis.mapper.typehandler; import java.io.Serializable; /** * @author liuzh */ public class Address implements Serializable { private static final long serialVersionUID = 1L; private String province; private String city; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { StringBuilder builder = new StringBuilder(); if (province != null && province.length() > 0) { builder.append(province); } if (city != null && city.length() > 0) { builder.append("/").append(city); } return builder.toString(); } public static void main(String[] args) { System.out.println("/hh".split("/").length); System.out.println("/hh".split("/")[0]); System.out.println("/hh".split("/")[1]); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/AddressTypeHandler.java ================================================ package tk.mybatis.mapper.typehandler; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * @author liuzh */ public class AddressTypeHandler extends BaseTypeHandler

{ @Override public void setNonNullParameter(PreparedStatement ps, int i, Address parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.toString()); } private Address convertToAddress(String addressStr) { if (addressStr == null || addressStr.length() == 0) { return null; } String[] strings = addressStr.split("/"); Address address = new Address(); if (strings.length > 0 && strings[0].length() > 0) { address.setProvince(strings[0]); } if (strings.length > 1 && strings[1].length() > 0) { address.setCity(strings[1]); } return address; } @Override public Address getNullableResult(ResultSet rs, String columnName) throws SQLException { return convertToAddress(rs.getString(columnName)); } @Override public Address getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return convertToAddress(rs.getString(columnIndex)); } @Override public Address getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return convertToAddress(cs.getString(columnIndex)); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/CreateDB.sql ================================================ drop table user if exists; create table user ( id integer NOT NULL PRIMARY KEY, name varchar(32), address varchar(64), state integer ); INSERT INTO user (id, name, address, state) VALUES (1, 'abel533', 'Hebei/Shijiazhuang', 1); INSERT INTO user (id, name, address, state) VALUES (2, 'isea533', 'Hebei/Handan', 0); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/StateEnum.java ================================================ package tk.mybatis.mapper.typehandler; /** * @author liuzh */ public enum StateEnum { disabled, enabled, } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/StateEnumTypeHandler.java ================================================ package tk.mybatis.mapper.typehandler; import org.apache.ibatis.type.EnumOrdinalTypeHandler; public class StateEnumTypeHandler extends EnumOrdinalTypeHandler { public StateEnumTypeHandler(Class type) { super(type); } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/TypeHandlerTest.java ================================================ package tk.mybatis.mapper.typehandler; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.entity.Config; import java.io.IOException; import java.io.Reader; import java.util.List; /** * @author liuzh */ public class TypeHandlerTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setEnumAsSimpleType(true); return config; } @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(TypeHandlerTest.class.getResource("mybatis-config-typehandler.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return toReader(TypeHandlerTest.class.getResource("CreateDB.sql")); } @Test public void testSelect() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List users = userMapper.selectAll(); Assert.assertNotNull(users); Assert.assertEquals(2, users.size()); Assert.assertEquals("abel533", users.get(0).getName()); Assert.assertEquals("Hebei", users.get(0).getAddress().getProvince()); Assert.assertEquals("Shijiazhuang", users.get(0).getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, users.get(0).getState()); Assert.assertEquals("isea533", users.get(1).getName()); Assert.assertEquals("Hebei/Handan", users.get(1).getAddress().toString()); Assert.assertEquals(StateEnum.disabled, users.get(1).getState()); User user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Shijiazhuang", user.getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testInsert() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setId(3); user.setName("liuzh"); Address address = new Address(); address.setProvince("Hebei"); address.setCity("Qinhuangdao"); user.setAddress(address); user.setState(StateEnum.enabled); Assert.assertEquals(1, userMapper.insert(user)); user = userMapper.selectByPrimaryKey(3); Assert.assertEquals("liuzh", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Qinhuangdao", user.getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testUpdate() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Shijiazhuang", user.getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, user.getState()); user.setState(StateEnum.disabled); user.getAddress().setCity("Handan"); Assert.assertEquals(1, userMapper.updateByPrimaryKey(user)); user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Handan", user.getAddress().getCity()); Assert.assertEquals(StateEnum.disabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testDelete() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Assert.assertEquals(1, userMapper.deleteByPrimaryKey(1)); User user = new User(); Address address = new Address(); address.setProvince("Hebei"); address.setCity("Handan"); user.setAddress(address); user.setState(StateEnum.enabled); Assert.assertEquals(0, userMapper.delete(user)); user.setState(StateEnum.disabled); Assert.assertEquals(1, userMapper.delete(user)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/TypeHandlerTest2.java ================================================ package tk.mybatis.mapper.typehandler; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import tk.mybatis.mapper.entity.Config; import java.io.IOException; import java.io.Reader; import java.util.List; /** * @author liuzh */ public class TypeHandlerTest2 extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); config.setEnumAsSimpleType(true); return config; } @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(TypeHandlerTest2.class.getResource("mybatis-config-typehandler2.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return toReader(TypeHandlerTest2.class.getResource("CreateDB.sql")); } @Test public void testSelect() { SqlSession sqlSession = getSqlSession(); try { User2Mapper userMapper = sqlSession.getMapper(User2Mapper.class); List users = userMapper.selectAll(); Assert.assertNotNull(users); Assert.assertEquals(2, users.size()); Assert.assertEquals("abel533", users.get(0).getName()); Assert.assertEquals("Hebei", users.get(0).getAddress().getProvince()); Assert.assertEquals("Shijiazhuang", users.get(0).getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, users.get(0).getState()); Assert.assertEquals("isea533", users.get(1).getName()); Assert.assertEquals("Hebei/Handan", users.get(1).getAddress().toString()); Assert.assertEquals(StateEnum.disabled, users.get(1).getState()); User2 user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Shijiazhuang", user.getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testInsert() { SqlSession sqlSession = getSqlSession(); try { User2Mapper userMapper = sqlSession.getMapper(User2Mapper.class); User2 user = new User2(); user.setId(3); user.setName("liuzh"); Address address = new Address(); address.setProvince("Hebei"); address.setCity("Qinhuangdao"); user.setAddress(address); user.setState(StateEnum.enabled); Assert.assertEquals(1, userMapper.insert(user)); user = userMapper.selectByPrimaryKey(3); Assert.assertEquals("liuzh", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Qinhuangdao", user.getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testUpdate() { SqlSession sqlSession = getSqlSession(); try { User2Mapper userMapper = sqlSession.getMapper(User2Mapper.class); User2 user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Shijiazhuang", user.getAddress().getCity()); Assert.assertEquals(StateEnum.enabled, user.getState()); user.setState(StateEnum.disabled); user.getAddress().setCity("Handan"); Assert.assertEquals(1, userMapper.updateByPrimaryKey(user)); user = userMapper.selectByPrimaryKey(1); Assert.assertEquals("abel533", user.getName()); Assert.assertEquals("Hebei", user.getAddress().getProvince()); Assert.assertEquals("Handan", user.getAddress().getCity()); Assert.assertEquals(StateEnum.disabled, user.getState()); } finally { sqlSession.close(); } } @Test public void testDelete() { SqlSession sqlSession = getSqlSession(); try { User2Mapper userMapper = sqlSession.getMapper(User2Mapper.class); Assert.assertEquals(1, userMapper.deleteByPrimaryKey(1)); User2 user = new User2(); Address address = new Address(); address.setProvince("Hebei"); address.setCity("Handan"); user.setAddress(address); user.setState(StateEnum.enabled); Assert.assertEquals(0, userMapper.delete(user)); user.setState(StateEnum.disabled); Assert.assertEquals(1, userMapper.delete(user)); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/User.java ================================================ package tk.mybatis.mapper.typehandler; import tk.mybatis.mapper.annotation.ColumnType; import jakarta.persistence.Id; import java.io.Serializable; /** * @author liuzh */ public class User implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String name; @ColumnType(typeHandler = AddressTypeHandler.class) private Address address; //@ColumnType(typeHandler = StateEnumTypeHandler.class) private StateEnum state; public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public StateEnum getState() { return state; } public void setState(StateEnum state) { this.state = state; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/User2.java ================================================ package tk.mybatis.mapper.typehandler; import jakarta.persistence.Column; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; /** * @author liuzh */ @Table(name = "user") public class User2 implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String name; @Column private Address address; private StateEnum state; public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public StateEnum getState() { return state; } public void setState(StateEnum state) { this.state = state; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/User2Mapper.java ================================================ package tk.mybatis.mapper.typehandler; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface User2Mapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/UserMapper.java ================================================ package tk.mybatis.mapper.typehandler; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/mybatis-config-typehandler.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/typehandler/mybatis-config-typehandler2.xml ================================================ ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/CreateDB.sql ================================================ drop table user_timestamp if exists; CREATE TABLE user_timestamp ( id int NOT NULL, join_date TIMESTAMP DEFAULT NULL, PRIMARY KEY (id) ); insert into user_timestamp values (999, TIMESTAMP '2019-01-01 01:01:11'); drop table user_int if exists; CREATE TABLE user_int ( id int NOT NULL, age int DEFAULT NULL, PRIMARY KEY (id) ); insert into user_int values (999, 30); ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/UserInt.java ================================================ package tk.mybatis.mapper.version; import tk.mybatis.mapper.annotation.Version; import jakarta.persistence.Id; import jakarta.persistence.Table; /** * @author liuzh */ @Table(name = "user_int") public class UserInt { @Id private Integer id; @Version private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/UserIntMapper.java ================================================ package tk.mybatis.mapper.version; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserIntMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/UserTimestamp.java ================================================ package tk.mybatis.mapper.version; import tk.mybatis.mapper.annotation.Version; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.sql.Timestamp; /** * @author liuzh */ @Table(name = "user_timestamp") public class UserTimestamp { @Id private Integer id; @Version private Timestamp joinDate; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Timestamp getJoinDate() { return joinDate; } public void setJoinDate(Timestamp joinDate) { this.joinDate = joinDate; } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/UserTimestampMapper.java ================================================ package tk.mybatis.mapper.version; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh */ public interface UserTimestampMapper extends Mapper { } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/VersionTest.java ================================================ package tk.mybatis.mapper.version; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.base.BaseTest; import java.io.IOException; import java.io.Reader; import java.sql.Timestamp; import static org.junit.Assert.*; /** * @author liuzh */ public class VersionTest extends BaseTest { @Override protected Reader getConfigFileAsReader() throws IOException { return toReader(VersionTest.class.getResource("mybatis-config-version.xml")); } @Override protected Reader getSqlFileAsReader() throws IOException { return toReader(VersionTest.class.getResource("CreateDB.sql")); } @Test public void testInsert() { SqlSession sqlSession = getSqlSession(); try { UserTimestampMapper mapper = sqlSession.getMapper(UserTimestampMapper.class); UserTimestamp user = new UserTimestamp(); user.setId(1); user.setJoinDate(new Timestamp(System.currentTimeMillis())); int count = mapper.insert(user); assertEquals(1, count); } finally { sqlSession.close(); } } @Test public void testUpdate() { SqlSession sqlSession = getSqlSession(); try { UserTimestampMapper mapper = sqlSession.getMapper(UserTimestampMapper.class); UserTimestamp user = mapper.selectByPrimaryKey(999); assertNotNull(user); Timestamp joinDate = user.getJoinDate(); int count = mapper.updateByPrimaryKey(user); assertEquals(1, count); user = mapper.selectByPrimaryKey(999); assertFalse(joinDate.equals(user.getJoinDate())); } finally { sqlSession.close(); } } @Test public void testUpdateByPrimaryKeySelective() { SqlSession sqlSession = getSqlSession(); try { UserTimestampMapper mapper = sqlSession.getMapper(UserTimestampMapper.class); UserTimestamp user = mapper.selectByPrimaryKey(999); assertNotNull(user); Timestamp joinDate = user.getJoinDate(); int count = mapper.updateByPrimaryKeySelective(user); assertEquals(1, count); user = mapper.selectByPrimaryKey(999); assertFalse(joinDate.equals(user.getJoinDate())); } finally { sqlSession.close(); } } @Test public void testUpdateInt() { SqlSession sqlSession = getSqlSession(); try { UserIntMapper mapper = sqlSession.getMapper(UserIntMapper.class); UserInt user = mapper.selectByPrimaryKey(999); assertNotNull(user); Integer age = user.getAge(); int count = mapper.updateByPrimaryKey(user); assertEquals(1, count); user = mapper.selectByPrimaryKey(999); assertFalse(age.equals(user.getAge())); } finally { sqlSession.close(); } } @Test public void testUpdateIntByPrimaryKeySelective() { SqlSession sqlSession = getSqlSession(); try { UserIntMapper mapper = sqlSession.getMapper(UserIntMapper.class); UserInt user = mapper.selectByPrimaryKey(999); assertNotNull(user); Integer age = user.getAge(); int count = mapper.updateByPrimaryKeySelective(user); assertEquals(1, count); user = mapper.selectByPrimaryKey(999); assertFalse(age.equals(user.getAge())); } finally { sqlSession.close(); } } } ================================================ FILE: base/src/test/java/tk/mybatis/mapper/version/mybatis-config-version.xml ================================================ ================================================ FILE: base/src/test/resources/CachedCountryMapper.xml ================================================ ================================================ FILE: base/src/test/resources/CreateDB.sql ================================================ drop table country if exists; create table country ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) DEFAULT 'HH', version INTEGER DEFAULT 1 NOT NULL ); drop table country2 if exists; create table country2 ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL PRIMARY KEY, countryname varchar(32), countrycode varchar(2) DEFAULT 'HH' ); drop table country_t if exists; create table country_t ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL PRIMARY KEY, countryname varchar(32) ); drop table country_jdbc if exists; create table country_jdbc ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL PRIMARY KEY, countryname varchar(128), countrycode varchar(2) ); drop table country_i if exists; create table country_i ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL PRIMARY KEY, countryname varchar(128), countrycode varchar(2) DEFAULT 'HH' ); --用户信息表 drop table user_info if exists; create table user_info ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 6) NOT NULL PRIMARY KEY, username varchar(32) NOT NULL, password varchar(32) DEFAULT '12345678', usertype varchar(2), enabled integer, realname varchar(50), qq varchar(12), email varchar(100), address varchar(200), tel varchar(30) ); --用户信息表 drop table user_info_map if exists; create table user_info_map ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 6) NOT NULL PRIMARY KEY, user_name varchar(32) NOT NULL, password varchar(32) DEFAULT '12345678', user_type varchar(2), real_name varchar(50) ); insert into user_info (id, username, password, usertype) values (1, 'test1', '12345678', '1'); insert into user_info (id, username, password, usertype) values (2, 'test2', 'aaaa', '2'); insert into user_info (id, username, password, usertype) values (3, 'test3', 'bbbb', '1'); insert into user_info (id, username, password, usertype) values (4, 'test4', 'cccc', '2'); insert into user_info (id, username, password, usertype) values (5, 'test5', 'dddd', '1'); insert into user_info_map (id, user_name, password, user_type) values (1, 'test1', '12345678', '1'); insert into user_info_map (id, user_name, password, user_type) values (2, 'test2', 'aaaa', '2'); insert into user_info_map (id, user_name, password, user_type) values (3, 'test3', 'bbbb', '1'); insert into user_info_map (id, user_name, password, user_type) values (4, 'test4', 'cccc', '2'); insert into user_info_map (id, user_name, password, user_type) values (5, 'test5', 'dddd', '1'); --用户登录表,logid和username联合主键 drop table user_login if exists; create table user_login ( logid integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL, username varchar(32) NOT NULL, logindate DATETIME, loginip varchar(16), PRIMARY KEY (logid, username) ); insert into user_login (logid, username, logindate, loginip) values (1, 'test1', '2014-10-11 12:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (2, 'test1', '2014-10-21 12:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (3, 'test1', '2014-10-21 14:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (4, 'test1', '2014-11-21 11:20:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (5, 'test1', '2014-11-21 13:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (6, 'test2', '2014-11-21 12:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (7, 'test2', '2014-11-21 12:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (8, 'test3', '2014-11-21 12:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (9, 'test4', '2014-11-21 12:00:00', '192.168.1.123'); insert into user_login (logid, username, logindate, loginip) values (10, 'test5', '2014-11-21 12:00:00', '192.168.1.123'); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (13, 'Bahamas', 'BS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (14, 'Bahrain', 'BH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (15, 'Bangladesh', 'BD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (16, 'Barbados', 'BB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (17, 'Belarus', 'BY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (18, 'Belgium', 'BE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (19, 'Belize', 'BZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (20, 'Benin', 'BJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (21, 'Bermuda Is.', 'BM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (22, 'Bolivia', 'BO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (23, 'Botswana', 'BW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (24, 'Brazil', 'BR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (25, 'Brunei', 'BN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (26, 'Bulgaria', 'BG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (27, 'Burkina-faso', 'BF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (28, 'Burma', 'MM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (29, 'Burundi', 'BI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (30, 'Cameroon', 'CM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (31, 'Canada', 'CA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (32, 'Central African Republic', 'CF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (33, 'Chad', 'TD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (34, 'Chile', 'CL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (35, 'China', 'CN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (36, 'Colombia', 'CO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (37, 'Congo', 'CG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (38, 'Cook Is.', 'CK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (39, 'Costa Rica', 'CR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (40, 'Cuba', 'CU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (41, 'Cyprus', 'CY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (42, 'Czech Republic', 'CZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (43, 'Denmark', 'DK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (44, 'Djibouti', 'DJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (45, 'Dominica Rep.', 'DO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (46, 'Ecuador', 'EC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (47, 'Egypt', 'EG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (48, 'EI Salvador', 'SV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (49, 'Estonia', 'EE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (50, 'Ethiopia', 'ET', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (51, 'Fiji', 'FJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (52, 'Finland', 'FI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (53, 'France', 'FR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (54, 'French Guiana', 'GF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (55, 'Gabon', 'GA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (56, 'Gambia', 'GM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (57, 'Georgia', 'GE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (58, 'Germany', 'DE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (59, 'Ghana', 'GH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (60, 'Gibraltar', 'GI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (61, 'Greece', 'GR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (62, 'Grenada', 'GD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (63, 'Guam', 'GU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (64, 'Guatemala', 'GT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (65, 'Guinea', 'GN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (66, 'Guyana', 'GY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (67, 'Haiti', 'HT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (68, 'Honduras', 'HN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (69, 'Hongkong', 'HK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (70, 'Hungary', 'HU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (71, 'Iceland', 'IS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (72, 'India', 'IN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (73, 'Indonesia', 'ID', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (74, 'Iran', 'IR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (75, 'Iraq', 'IQ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (76, 'Ireland', 'IE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (77, 'Israel', 'IL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (78, 'Italy', 'IT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (79, 'Jamaica', 'JM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (80, 'Japan', 'JP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (81, 'Jordan', 'JO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (82, 'Kampuchea (Cambodia )', 'KH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (83, 'Kazakstan', 'KZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (84, 'Kenya', 'KE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (85, 'Korea', 'KR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (86, 'Kuwait', 'KW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (87, 'Kyrgyzstan', 'KG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (88, 'Laos', 'LA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (89, 'Latvia', 'LV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (90, 'Lebanon', 'LB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (91, 'Lesotho', 'LS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (92, 'Liberia', 'LR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (93, 'Libya', 'LY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (94, 'Liechtenstein', 'LI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (95, 'Lithuania', 'LT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (96, 'Luxembourg', 'LU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (97, 'Macao', 'MO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (98, 'Madagascar', 'MG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (99, 'Malawi', 'MW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (100, 'Malaysia', 'MY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (101, 'Maldives', 'MV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (102, 'Mali', 'ML', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (103, 'Malta', 'MT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (104, 'Mauritius', 'MU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (105, 'Mexico', 'MX', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (106, 'Moldova, Republic of', 'MD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (107, 'Monaco', 'MC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (108, 'Mongolia', 'MN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (109, 'Montserrat Is', 'MS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (110, 'Morocco', 'MA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (111, 'Mozambique', 'MZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (112, 'Namibia', 'NA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (113, 'Nauru', 'NR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (114, 'Nepal', 'NP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (115, 'Netherlands', 'NL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (116, 'New Zealand', 'NZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (117, 'Nicaragua', 'NI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (118, 'Niger', 'NE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (119, 'Nigeria', 'NG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (120, 'North Korea', 'KP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (121, 'Norway', 'NO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (122, 'Oman', 'OM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (123, 'Pakistan', 'PK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (124, 'Panama', 'PA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (125, 'Papua New Cuinea', 'PG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (126, 'Paraguay', 'PY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (127, 'Peru', 'PE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (128, 'Philippines', 'PH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (129, 'Poland', 'PL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (130, 'French Polynesia', 'PF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (131, 'Portugal', 'PT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (132, 'Puerto Rico', 'PR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (133, 'Qatar', 'QA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (134, 'Romania', 'RO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (135, 'Russia', 'RU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (136, 'Saint Lueia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (137, 'Saint Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (138, 'San Marino', 'SM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (139, 'Sao Tome and Principe', 'ST', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (140, 'Saudi Arabia', 'SA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (141, 'Senegal', 'SN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (142, 'Seychelles', 'SC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (143, 'Sierra Leone', 'SL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (144, 'Singapore', 'SG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (145, 'Slovakia', 'SK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (146, 'Slovenia', 'SI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (147, 'Solomon Is', 'SB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (148, 'Somali', 'SO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (149, 'South Africa', 'ZA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (150, 'Spain', 'ES', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (151, 'Sri Lanka', 'LK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (152, 'St.Lucia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (153, 'St.Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (154, 'Sudan', 'SD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (155, 'Suriname', 'SR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (156, 'Swaziland', 'SZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (157, 'Sweden', 'SE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (158, 'Switzerland', 'CH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (159, 'Syria', 'SY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (160, 'Taiwan', 'TW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (161, 'Tajikstan', 'TJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (162, 'Tanzania', 'TZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (163, 'Thailand', 'TH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (164, 'Togo', 'TG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (165, 'Tonga', 'TO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (166, 'Trinidad and Tobago', 'TT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (167, 'Tunisia', 'TN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (168, 'Turkey', 'TR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (169, 'Turkmenistan', 'TM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (170, 'Uganda', 'UG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (171, 'Ukraine', 'UA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (172, 'United Arab Emirates', 'AE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (173, 'United Kiongdom', 'GB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (174, 'United States of America', 'US', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (175, 'Uruguay', 'UY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (176, 'Uzbekistan', 'UZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (177, 'Venezuela', 'VE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (178, 'Vietnam', 'VN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (179, 'Yemen', 'YE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (180, 'Yugoslavia', 'YU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (181, 'Zimbabwe', 'ZW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (182, 'Zaire', 'ZR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (183, 'Zambia', 'ZM', 1); insert into country_t (id, countryname) values (174, 'United States of America'); --用户信息表 drop table tb_user if exists; create table tb_user ( id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 6) NOT NULL PRIMARY KEY, username varchar(32) NOT NULL, password varchar(32) DEFAULT '12345678', is_valid integer ); insert into tb_user (id, username, password, is_valid) values (1, 'test1', '12345678', 1); insert into tb_user (id, username, password, is_valid) values (2, 'test2', 'aaaa', 1); insert into tb_user (id, username, password, is_valid) values (3, 'test3', 'bbbb', 1); insert into tb_user (id, username, password, is_valid) values (4, 'test4', 'cccc', 1); insert into tb_user (id, username, password, is_valid) values (5, 'test5', 'dddd', 0); insert into tb_user (id, username, password, is_valid) values (6, 'test6', 'eeee', 0); insert into tb_user (id, username, password, is_valid) values (7, 'test7', 'ffff', 0); insert into tb_user (id, username, password, is_valid) values (8, 'test', 'gggg', 1); insert into tb_user (id, username, password, is_valid) values (9, 'test', 'gggg', 0); ================================================ FILE: base/src/test/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: base/src/test/resources/mybatis-java.xml ================================================ ================================================ FILE: core/README.md ================================================ # MyBatis通用Mapper3 [![Build Status](https://travis-ci.org/abel533/Mapper.svg?branch=master)](https://travis-ci.org/abel533/Mapper) [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper) [![Dependency Status](https://www.versioneye.com/user/projects/593212c722f278006540a1d1/badge.svg?style=flat)](https://www.versioneye.com/user/projects/593212c722f278006540a1d1) 通用Mapper都可以极大的方便开发人员。可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方法。 极其方便的使用MyBatis单表的增删改查。 支持单表操作,不支持通用的多表联合查询。 ## 新书《MyBatis 从入门到精通》 ![MyBatis 从入门到精通](https://github.com/mybatis-book/book/raw/master/book.png) 购买地址:[京东](https://item.jd.com/12103309.html),[当当](http://product.dangdang.com/25098208.html),[亚马逊](https://www.amazon.cn/MyBatis从入门到精通-刘增辉/dp/B072RC11DM/ref=sr_1_18?ie=UTF8&qid=1498007125&sr=8-18&keywords=mybatis) CSDN博客:http://blog.csdn.net/isea533/article/details/73555400 GitHub项目:https://github.com/mybatis-book/book ## 通用 Mapper 支持 Mybatis-3.2.4 及以上版本 ## 不是表中字段的属性必须加 `@Transient` 注解 ## Spring DevTools 配置 感谢[emf1002](https://github.com/emf1002)提供的解决方案。 在使用 DevTools 时,通用Mapper经常会出现 `class x.x.A cannot be cast to x.x.A`。 同一个类如果使用了不同的类加载器,就会产生这样的错误,所以解决方案就是让通用Mapper和实体类使用相同的类加载器即可。 DevTools 默认会对 IDE 中引入的所有项目使用 restart 类加载器,对于引入的 jar 包使用 base 类加载器,因此只要保证通用Mapper的jar包使用 restart 类加载器即可。 在 `src/main/resources` 中创建 META-INF 目录,在此目录下添加 spring-devtools.properties 配置,内容如下: ```properties restart.include.mapper=/mapper-[\\w-\\.]+jar restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar ``` 使用这个配置后,就会使用 restart 类加载加载 include 进去的 jar 包。 ## 项目文档 ### https://mapperhelper.github.io 在你打算使用通用 Mapper 前,一定要看看下面的文档,许多人在初次使用时遇到的问题,99% 都在文档中有说明!! 1. [如何集成通用Mapper](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/2.Integration.md) 2. [如何使用通用Mapper](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/3.Use.md) 2. [3.3.0版本新增功能用法文档](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/3.2.Use330.md) 3. [根据需要自定义接口](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/4.Professional.md) 4. [Mapper3通用接口大全](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/5.Mappers.md) 5. [扩展通用接口](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/6.MyMapper.md) 6. [使用Mapper专用的MyBatis生成器插件](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/7.UseMBG.md) 7. [在Spring4中使用通用Mapper](http://git.oschina.net/free/Mapper2/blob/master/wiki/mapper/4.Spring4.md) 8. [Mapper3常见问题和用法](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/9.QA.md) ### 如何让作者为你开发通用方法? 实际上,只要你看看上面的第 6 个文档,你完全可以自己开发出来。 或者你可以通过赞助作者 10~50 元来让作者根据你的需求开发**一个**通用方法。 赞助后保留截图,将截图和需求内容发邮件到 abel533@gmail.com 和作者联系。 你还可以通过开源中国众包购买服务[开发 MyBatis 通用 Mapper 通用方法](https://zb.oschina.net/market/opus/92cda9e3bc85365f) ## 通用 Mapper - 简单用法示例 全部针对单表操作,每个实体类都需要继承通用Mapper接口来获得通用方法。 示例代码: CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); //查询全部 List countryList = mapper.select(new Country()); //总数 Assert.assertEquals(183, countryList.size()); //通用Example查询 Example example = new Example(Country.class); example.createCriteria().andGreaterThan("id", 100); countryList = mapper.selectByExample(example); Assert.assertEquals(83, countryList.size()); //MyBatis-Generator生成的Example查询 CountryExample example2 = new CountryExample(); example2.createCriteria().andIdGreaterThan(100); countryList = mapper.selectByExample(example2); Assert.assertEquals(83, countryList.size()); CountryMapper代码如下: public interface CountryMapper extends Mapper { } 这里不说更具体的内容,如果您有兴趣,可以查看下面的项目文档 ## 实体类注解 从上面效果来看也能感觉出这是一种类似hibernate的用法,因此也需要实体和表对应起来,因此使用了JPA注解。更详细的内容可以看下面的项目文档。 Country代码: public class Country { @Id private Integer id; @Column private String countryname; private String countrycode; //省略setter和getter方法 } [使用Mapper专用的MyBatis Generator插件](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/7.UseMBG.md) 可以方便的生成这些(带注解的)实体类。 ## 使用 Maven ```xml tk.mybatis mapper 最新版本 ``` 如果你使用 Spring Boot 可以直接引入: ```xml tk.mybatis mapper-spring-boot-starter 最新版本 ``` 具体用法可以参考:[MyBatis-Spring-Boot](https://github.com/abel533/MyBatis-Spring-Boot) ## 引入 Jar 包,下载地址: https://oss.sonatype.org/content/repositories/releases/tk/mybatis/mapper http://repo1.maven.org/maven2/tk/mybatis/mapper 由于通用Mapper依赖JPA,所以还需要下载persistence-api-1.0.jar: http://repo1.maven.org/maven2/javax/persistence/persistence-api/1.0/ ## [更新日志](http://git.oschina.net/free/Mapper/blob/master/wiki/Changelog.md) ## 作者信息 MyBatis 工具网站:[https://mybatis.io](https://mybatis.io) 作者博客:http://blog.csdn.net/isea533 作者邮箱: abel533@gmail.com 如需加群,请通过 https://mybatis.io 首页按钮加群。 推荐使用Mybatis分页插件:[PageHelper分页插件](https://github.com/pagehelper/Mybatis-PageHelper) ================================================ FILE: core/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-core jar mapper-core Mybatis 通用 Mapper https://mybatis.io org.slf4j slf4j-api jakarta.persistence jakarta.persistence-api org.mybatis mybatis ================================================ FILE: core/src/main/java/tk/mybatis/mapper/LogicDeleteException.java ================================================ package tk.mybatis.mapper; public class LogicDeleteException extends RuntimeException { public LogicDeleteException() { super(); } public LogicDeleteException(String message) { super(message); } public LogicDeleteException(String message, Throwable cause) { super(message, cause); } public LogicDeleteException(Throwable cause) { super(cause); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/MapperException.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper; /** * @author liuzh */ public class MapperException extends RuntimeException { public MapperException() { super(); } public MapperException(String message) { super(message); } public MapperException(String message, Throwable cause) { super(message, cause); } public MapperException(Throwable cause) { super(cause); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/ColumnType.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.annotation; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.UnknownTypeHandler; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 针对列的复杂属性配置 * * @author liuzh * @since 2015-10-29 22:00 */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ColumnType { String column() default ""; /** * 是否为 BLOB 字段 * * @return */ boolean isBlob() default false; JdbcType jdbcType() default JdbcType.UNDEFINED; Class typeHandler() default UnknownTypeHandler.class; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/KeySql.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.annotation; import tk.mybatis.mapper.code.IdentityDialect; import tk.mybatis.mapper.code.ORDER; import tk.mybatis.mapper.genid.GenId; import tk.mybatis.mapper.gensql.GenSql; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 主键策略,用于替换 JPA 中的复杂用法 * * @author liuzh * @since 2015-10-29 22:00 */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface KeySql { /** * 是否使用 JDBC 方式获取主键,优先级最高,设置为 true 后,不对其他配置校验 * * @return */ boolean useGeneratedKeys() default false; /** * 优先级第二,根据配置的数据库类型取回主键,忽略其他配置 * * @return */ IdentityDialect dialect() default IdentityDialect.NULL; /** * 取主键的 SQL * * @return */ String sql() default ""; /** * 生成 SQL,初始化时执行,优先级低于 sql * * @return */ Class genSql() default GenSql.NULL.class; /** * 和 sql 可以配合使用,默认使用全局配置中的 ORDER * * @return */ ORDER order() default ORDER.DEFAULT; /** * Java 方式生成主键,可以和发号器一类的服务配合使用 * * @return */ Class genId() default GenId.NULL.class; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/LogicDelete.java ================================================ package tk.mybatis.mapper.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 逻辑删除 */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface LogicDelete { int isDeletedValue() default 1; /** * 优先级比isDeletedValue更高 表示以null作为删除记录的标识 */ boolean isNullForDeletedValue() default false; int notDeletedValue() default 0; /** * 优先级比notDeletedValue更高 表示以null作为未删除记录的标识 */ boolean isNullForNotDeletedValue() default false; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/NameStyle.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.annotation; import tk.mybatis.mapper.code.Style; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 名字转换样式,注解的优先级高于全局配置 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface NameStyle { Style value() default Style.normal; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/Order.java ================================================ package tk.mybatis.mapper.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @description: 字段排序 * @author: qrqhuangcy * @date: 2018-11-11 **/ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Order { /** * 升降序 * * @return */ String value() default "ASC"; /** * 优先级, 值小的优先 * * @return */ int priority() default 1; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/RegisterMapper.java ================================================ package tk.mybatis.mapper.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 自动注册 Mapper 接口标记 * * @author liuzh * @since 3.6.0 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface RegisterMapper { } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/annotation/Version.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.annotation; import tk.mybatis.mapper.version.DefaultNextVersion; import tk.mybatis.mapper.version.NextVersion; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author liuzh * @since 3.5.0 */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Version { /** * 下一个版本号的算法,默认算法支持 Integer 和 Long,在原基础上 +1 * * @return */ Class nextVersion() default DefaultNextVersion.class; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/code/IdentityDialect.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.code; /** * @author liuzh */ public enum IdentityDialect { DB2("VALUES IDENTITY_VAL_LOCAL()"), MYSQL("SELECT LAST_INSERT_ID()"), SQLSERVER("SELECT SCOPE_IDENTITY()"), CLOUDSCAPE("VALUES IDENTITY_VAL_LOCAL()"), DERBY("VALUES IDENTITY_VAL_LOCAL()"), HSQLDB("CALL IDENTITY()"), SYBASE("SELECT @@IDENTITY"), DB2_MF("SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"), INFORMIX("select dbinfo('sqlca.sqlerrd1') from systables where tabid=1"), DEFAULT(""), NULL(""); private String identityRetrievalStatement; private IdentityDialect(String identityRetrievalStatement) { this.identityRetrievalStatement = identityRetrievalStatement; } public static IdentityDialect getDatabaseDialect(String database) { IdentityDialect returnValue = null; if ("DB2".equalsIgnoreCase(database)) { returnValue = DB2; } else if ("MySQL".equalsIgnoreCase(database)) { returnValue = MYSQL; } else if ("SqlServer".equalsIgnoreCase(database)) { returnValue = SQLSERVER; } else if ("Cloudscape".equalsIgnoreCase(database)) { returnValue = CLOUDSCAPE; } else if ("Derby".equalsIgnoreCase(database)) { returnValue = DERBY; } else if ("HSQLDB".equalsIgnoreCase(database)) { returnValue = HSQLDB; } else if ("SYBASE".equalsIgnoreCase(database)) { returnValue = SYBASE; } else if ("DB2_MF".equalsIgnoreCase(database)) { returnValue = DB2_MF; } else if ("Informix".equalsIgnoreCase(database)) { returnValue = INFORMIX; } else if ("".equals(database)) { return DEFAULT; } return returnValue; } public String getIdentityRetrievalStatement() { return identityRetrievalStatement; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/code/ORDER.java ================================================ package tk.mybatis.mapper.code; /** * 执行 SQL 的时机 * * @author liuzh */ public enum ORDER { /** * insert 后执行 SQL */ AFTER, /** * insert 前执行 SQL */ BEFORE, /** * 使用全局配置 */ DEFAULT } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/code/Style.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.code; /** * 字段转换方式 */ public enum Style { /** * 原值 */ normal, /** * 驼峰转下划线 */ camelhump, /** * 转换为大写 */ uppercase, /** * 转换为小写 */ lowercase, /** * 驼峰转下划线大写形式 */ camelhumpAndUppercase, /** * 驼峰转下划线小写形式 */ camelhumpAndLowercase, } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/Condition.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; /** * Condition - 条件查询,命名就是任性 * * @author liuzh * @since 2015-06-10 */ public class Condition extends Example { public Condition(Class entityClass) { super(entityClass); } public Condition(Class entityClass, boolean exists) { super(entityClass, exists); } public Condition(Class entityClass, boolean exists, boolean notNull) { super(entityClass, exists, notNull); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/Config.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.code.IdentityDialect; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.mapperhelper.resolve.EntityResolve; import tk.mybatis.mapper.util.SimpleTypeUtil; import tk.mybatis.mapper.util.StringUtil; import java.util.ArrayList; import java.util.List; import java.util.Properties; /** * 通用Mapper属性配置 * * @author liuzh */ public class Config { public static final String PREFIX = "mapper"; private List mappers = new ArrayList(); private String IDENTITY; private boolean BEFORE; private String seqFormat; private String catalog; private String schema; //校验调用Example方法时,Example(entityClass)和Mapper是否一致 private boolean checkExampleEntityClass; //使用简单类型 //3.5.0 后默认值改为 true private boolean useSimpleType = true; /** * @since 3.5.0 */ private boolean enumAsSimpleType; /** * 是否支持方法上的注解,默认false */ private boolean enableMethodAnnotation; /** * 对于一般的getAllIfColumnNode,是否判断!='',默认不判断 */ private boolean notEmpty; /** * 字段转换风格,默认驼峰转下划线 */ private Style style; /** * 处理关键字,默认空,mysql可以设置为 `{0}`, sqlserver 为 [{0}],{0} 代表的列名 */ private String wrapKeyword = ""; /** * 配置解析器 */ private Class resolveClass; /** * 安全删除,开启后,不允许删全表,如 delete from table */ private boolean safeDelete; /** * 安全更新,开启后,不允许更新全表,如 update table set xx=? */ private boolean safeUpdate; /** * 控制通过主键进行操作(select, update, delete)时,是否拼接逻辑删除字段的条件(默认 true,保持兼容) *

* 设置为 false 时,通过主键查询或操作时不会追加 logicDeleteField = 0 的条件 */ private boolean logicDeleteByKey = true; /** * 是否设置 javaType */ private boolean useJavaType; /** * 是否自动处理 Mapper 接口中其他手写指定 resultType 的返回结果类型为 resultMap */ private boolean enableBaseResultMapFlag; public String getCatalog() { return catalog; } /** * 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename * * @param catalog */ public void setCatalog(String catalog) { this.catalog = catalog; } /** * 获取主键自增回写SQL * * @return */ public String getIDENTITY() { if (StringUtil.isNotEmpty(this.IDENTITY)) { return this.IDENTITY; } //针对mysql的默认值 return IdentityDialect.MYSQL.getIdentityRetrievalStatement(); } /** * 主键自增回写方法,默认值MYSQL,详细说明请看文档 * * @param IDENTITY */ public void setIDENTITY(String IDENTITY) { IdentityDialect identityDialect = IdentityDialect.getDatabaseDialect(IDENTITY); if (identityDialect != null) { this.IDENTITY = identityDialect.getIdentityRetrievalStatement(); } else { this.IDENTITY = IDENTITY; } } /** * 获取表前缀,带catalog或schema * * @return */ public String getPrefix() { if (StringUtil.isNotEmpty(this.catalog)) { return this.catalog; } if (StringUtil.isNotEmpty(this.schema)) { return this.schema; } return ""; } public String getSchema() { return schema; } /** * 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename *
如果同时设置了catalog,优先使用catalog.tablename * * @param schema */ public void setSchema(String schema) { this.schema = schema; } /** * 获取序列格式化模板 * * @return */ public String getSeqFormat() { if (StringUtil.isNotEmpty(this.seqFormat)) { return this.seqFormat; } return "{0}.nextval"; } /** * 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle *
可选参数一共3个,对应0,1,2,3分别为SequenceName,ColumnName, PropertyName,TableName * * @param seqFormat */ public void setSeqFormat(String seqFormat) { this.seqFormat = seqFormat; } public Style getStyle() { return this.style == null ? Style.camelhump : this.style; } public void setStyle(Style style) { this.style = style; } public String getWrapKeyword() { return wrapKeyword; } public void setWrapKeyword(String wrapKeyword) { this.wrapKeyword = wrapKeyword; } /** * 获取SelectKey的Order * * @return */ public boolean isBEFORE() { return BEFORE; } public void setBEFORE(boolean BEFORE) { this.BEFORE = BEFORE; } public boolean isCheckExampleEntityClass() { return checkExampleEntityClass; } public void setCheckExampleEntityClass(boolean checkExampleEntityClass) { this.checkExampleEntityClass = checkExampleEntityClass; } public boolean isEnableMethodAnnotation() { return enableMethodAnnotation; } public void setEnableMethodAnnotation(boolean enableMethodAnnotation) { this.enableMethodAnnotation = enableMethodAnnotation; } public boolean isEnumAsSimpleType() { return enumAsSimpleType; } public void setEnumAsSimpleType(boolean enumAsSimpleType) { this.enumAsSimpleType = enumAsSimpleType; } public boolean isNotEmpty() { return notEmpty; } public void setNotEmpty(boolean notEmpty) { this.notEmpty = notEmpty; } public boolean isUseSimpleType() { return useSimpleType; } public void setUseSimpleType(boolean useSimpleType) { this.useSimpleType = useSimpleType; } /** * 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER) * * @param order */ public void setOrder(String order) { this.BEFORE = "BEFORE".equalsIgnoreCase(order); } public String getIdentity() { return getIDENTITY(); } public void setIdentity(String identity) { setIDENTITY(identity); } public List getMappers() { return mappers; } public void setMappers(List mappers) { this.mappers = mappers; } public boolean isBefore() { return isBEFORE(); } public void setBefore(boolean before) { setBEFORE(before); } public Class getResolveClass() { return resolveClass; } public void setResolveClass(Class resolveClass) { this.resolveClass = resolveClass; } public boolean isSafeDelete() { return safeDelete; } public void setSafeDelete(boolean safeDelete) { this.safeDelete = safeDelete; } public boolean isSafeUpdate() { return safeUpdate; } public void setSafeUpdate(boolean safeUpdate) { this.safeUpdate = safeUpdate; } public boolean isLogicDeleteByKey() { return logicDeleteByKey; } public void setLogicDeleteByKey(boolean logicDeleteByKey) { this.logicDeleteByKey = logicDeleteByKey; } public boolean isUseJavaType() { return useJavaType; } public void setUseJavaType(boolean useJavaType) { this.useJavaType = useJavaType; } public boolean isEnableBaseResultMapFlag() { return enableBaseResultMapFlag; } public void setEnableBaseResultMapFlag(boolean enableBaseResultMapFlag) { this.enableBaseResultMapFlag = enableBaseResultMapFlag; } /** * 配置属性 * * @param properties */ public void setProperties(Properties properties) { if (properties == null) { //默认驼峰 this.style = Style.camelhump; return; } String IDENTITY = properties.getProperty("IDENTITY"); if (StringUtil.isNotEmpty(IDENTITY)) { setIDENTITY(IDENTITY); } String seqFormat = properties.getProperty("seqFormat"); if (StringUtil.isNotEmpty(seqFormat)) { setSeqFormat(seqFormat); } String catalog = properties.getProperty("catalog"); if (StringUtil.isNotEmpty(catalog)) { setCatalog(catalog); } String schema = properties.getProperty("schema"); if (StringUtil.isNotEmpty(schema)) { setSchema(schema); } //ORDER 有三个属性名可以进行配置 String ORDER = properties.getProperty("ORDER"); if (StringUtil.isNotEmpty(ORDER)) { setOrder(ORDER); } ORDER = properties.getProperty("order"); if (StringUtil.isNotEmpty(ORDER)) { setOrder(ORDER); } ORDER = properties.getProperty("before"); if (StringUtil.isNotEmpty(ORDER)) { setBefore(Boolean.valueOf(ORDER)); } this.notEmpty = Boolean.valueOf(properties.getProperty("notEmpty")); this.enableMethodAnnotation = Boolean.valueOf(properties.getProperty("enableMethodAnnotation")); this.checkExampleEntityClass = Boolean.valueOf(properties.getProperty("checkExampleEntityClass")); //默认值 true,所以要特殊判断 String useSimpleTypeStr = properties.getProperty("useSimpleType"); if (StringUtil.isNotEmpty(useSimpleTypeStr)) { this.useSimpleType = Boolean.valueOf(useSimpleTypeStr); } this.enumAsSimpleType = Boolean.valueOf(properties.getProperty("enumAsSimpleType")); //注册新的基本类型,以逗号隔开,使用全限定类名 String simpleTypes = properties.getProperty("simpleTypes"); if (StringUtil.isNotEmpty(simpleTypes)) { SimpleTypeUtil.registerSimpleType(simpleTypes); } //使用 8 种基本类型 if (Boolean.valueOf(properties.getProperty("usePrimitiveType"))) { SimpleTypeUtil.registerPrimitiveTypes(); } String styleStr = properties.getProperty("style"); if (StringUtil.isNotEmpty(styleStr)) { try { this.style = Style.valueOf(styleStr); } catch (IllegalArgumentException e) { throw new MapperException(styleStr + "不是合法的Style值!"); } } else { //默认驼峰 this.style = Style.camelhump; } //处理关键字 String wrapKeyword = properties.getProperty("wrapKeyword"); if (StringUtil.isNotEmpty(wrapKeyword)) { this.wrapKeyword = wrapKeyword; } //safeDelete this.safeDelete = Boolean.valueOf(properties.getProperty("safeDelete")); //safeUpdate this.safeUpdate = Boolean.valueOf(properties.getProperty("safeUpdate")); // 控制通过主键进行操作(select, update, delete)时,是否拼接逻辑删除字段的条件(默认 true,保持兼容) String logicDeleteByKey = properties.getProperty("logicDeleteByKey"); if (StringUtil.isNotEmpty(logicDeleteByKey)) { this.logicDeleteByKey = Boolean.valueOf(logicDeleteByKey); } //是否设置 javaType,true 时如 {id, javaType=java.lang.Long} this.useJavaType = Boolean.valueOf(properties.getProperty("useJavaType")); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/EntityColumn.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.code.ORDER; import tk.mybatis.mapper.genid.GenId; import tk.mybatis.mapper.util.StringUtil; /** * 数据库表对应的列 * * @author liuzh */ public class EntityColumn { private EntityTable table; private String property; private String column; private Class javaType; private JdbcType jdbcType; private Class typeHandler; private boolean id = false; private boolean identity = false; private Class genIdClass; //字段是否为 blob private boolean blob; private String generator; //排序 private String orderBy; private int orderPriority; //可插入 private boolean insertable = true; //可更新 private boolean updatable = true; private ORDER order = ORDER.DEFAULT; //是否设置 javaType private boolean useJavaType; /** * 对应的字段信息 * * @since 3.5.0 */ private EntityField entityField; public EntityColumn() { } public EntityColumn(EntityTable table) { this.table = table; } /** * 返回格式如:colum = #{entityName.age,jdbcType=NUMERIC,typeHandler=MyTypeHandler} * * @param entityName * @return */ public String getColumnEqualsHolder(String entityName) { return this.column + " = " + getColumnHolder(entityName); } /** * 返回格式如:#{entityName.age,jdbcType=NUMERIC,typeHandler=MyTypeHandler} * * @param entityName * @return */ public String getColumnHolder(String entityName) { return getColumnHolder(entityName, null); } /** * 返回格式如:#{entityName.age+suffix,jdbcType=NUMERIC,typeHandler=MyTypeHandler} * * @param entityName * @param suffix * @return */ public String getColumnHolder(String entityName, String suffix) { return getColumnHolder(entityName, null, null); } /** * 返回格式如:#{entityName.age+suffix,jdbcType=NUMERIC,typeHandler=MyTypeHandler}, * * @param entityName * @param suffix * @return */ public String getColumnHolderWithComma(String entityName, String suffix) { return getColumnHolder(entityName, suffix, ","); } /** * 返回格式如:#{entityName.age+suffix,jdbcType=NUMERIC,typeHandler=MyTypeHandler}+separator * * @param entityName * @param suffix * @param separator * @return */ public String getColumnHolder(String entityName, String suffix, String separator) { StringBuffer sb = new StringBuffer("#{"); if (StringUtil.isNotEmpty(entityName)) { sb.append(entityName); sb.append("."); } sb.append(this.property); if (StringUtil.isNotEmpty(suffix)) { sb.append(suffix); } //如果 null 被当作值来传递,对于所有可能为空的列,JDBC Type 是需要的 if (this.jdbcType != null) { sb.append(", jdbcType="); sb.append(this.jdbcType.toString()); } //为了以后定制类型处理方式,你也可以指定一个特殊的类型处理器类,例如枚举 if (this.typeHandler != null) { sb.append(", typeHandler="); sb.append(this.typeHandler.getName()); } //3.4.0 以前的 mybatis 无法获取父类中泛型的 javaType,所以如果使用低版本,就需要设置 useJavaType = true //useJavaType 默认 false,没有 javaType 限制时,对 ByPrimaryKey 方法的参数校验就放宽了,会自动转型 if (useJavaType && !this.javaType.isArray()) {//当类型为数组时,不设置javaType#103 sb.append(", javaType="); sb.append(javaType.getName()); } sb.append("}"); if (StringUtil.isNotEmpty(separator)) { sb.append(separator); } return sb.toString(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EntityColumn that = (EntityColumn) o; if (id != that.id) return false; if (identity != that.identity) return false; if (table != null ? !table.equals(that.table) : that.table != null) return false; if (property != null ? !property.equals(that.property) : that.property != null) return false; if (column != null ? !column.equals(that.column) : that.column != null) return false; if (javaType != null ? !javaType.equals(that.javaType) : that.javaType != null) return false; if (jdbcType != that.jdbcType) return false; if (typeHandler != null ? !typeHandler.equals(that.typeHandler) : that.typeHandler != null) return false; if (generator != null ? !generator.equals(that.generator) : that.generator != null) return false; return !(orderBy != null ? !orderBy.equals(that.orderBy) : that.orderBy != null); } @Override public int hashCode() { int result = table != null ? table.hashCode() : 0; result = 31 * result + (property != null ? property.hashCode() : 0); result = 31 * result + (column != null ? column.hashCode() : 0); result = 31 * result + (javaType != null ? javaType.hashCode() : 0); result = 31 * result + (jdbcType != null ? jdbcType.hashCode() : 0); result = 31 * result + (typeHandler != null ? typeHandler.hashCode() : 0); result = 31 * result + (id ? 1 : 0); result = 31 * result + (identity ? 1 : 0); result = 31 * result + (generator != null ? generator.hashCode() : 0); result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0); return result; } public String getColumn() { return column; } public void setColumn(String column) { this.column = column; } /** * 返回格式如:colum = #{age,jdbcType=NUMERIC,typeHandler=MyTypeHandler} * * @return */ public String getColumnEqualsHolder() { return getColumnEqualsHolder(null); } /** * 返回格式如:#{age,jdbcType=NUMERIC,typeHandler=MyTypeHandler} * * @return */ public String getColumnHolder() { return getColumnHolder(null); } public EntityField getEntityField() { return entityField; } public void setEntityField(EntityField entityField) { this.entityField = entityField; } public String getGenerator() { return generator; } public void setGenerator(String generator) { this.generator = generator; } public Class getJavaType() { return javaType; } public void setJavaType(Class javaType) { this.javaType = javaType; } public JdbcType getJdbcType() { return jdbcType; } public void setJdbcType(JdbcType jdbcType) { this.jdbcType = jdbcType; } public String getOrderBy() { return orderBy; } public void setOrderBy(String orderBy) { this.orderBy = orderBy; } public String getProperty() { return property; } public void setProperty(String property) { this.property = property; } public EntityTable getTable() { return table; } public void setTable(EntityTable table) { this.table = table; } public Class getTypeHandler() { return typeHandler; } public void setTypeHandler(Class typeHandler) { this.typeHandler = typeHandler; } public boolean isId() { return id; } public void setId(boolean id) { this.id = id; } public boolean isIdentity() { return identity; } public void setIdentity(boolean identity) { this.identity = identity; } public Class getGenIdClass() { return genIdClass; } public void setGenIdClass(Class genIdClass) { this.genIdClass = genIdClass; } public boolean isInsertable() { return insertable; } public void setInsertable(boolean insertable) { this.insertable = insertable; } public boolean isUpdatable() { return updatable; } public void setUpdatable(boolean updatable) { this.updatable = updatable; } public ORDER getOrder() { return order; } public void setOrder(ORDER order) { this.order = order; } public boolean isBlob() { return blob; } public void setBlob(boolean blob) { this.blob = blob; } public boolean isUseJavaType() { return useJavaType; } public void setUseJavaType(boolean useJavaType) { this.useJavaType = useJavaType; } public int getOrderPriority() { return orderPriority; } public void setOrderPriority(int orderPriority) { this.orderPriority = orderPriority; } @Override public String toString() { return "EntityColumn{" + "table=" + table.getName() + ", property='" + property + '\'' + ", column='" + column + '\'' + ", javaType=" + javaType + ", jdbcType=" + jdbcType + ", typeHandler=" + typeHandler + ", id=" + id + ", identity=" + identity + ", blob=" + blob + ", generator='" + generator + '\'' + ", orderBy='" + orderBy + '\'' + ", orderPriority='" + orderPriority + '\'' + ", insertable=" + insertable + ", updatable=" + updatable + ", order=" + order + '}'; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/EntityField.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 封装字段和方法,统一调用某些方法 * * @author liuzh */ public class EntityField { private String name; private Field field; private Class javaType; private Method setter; private Method getter; /** * 构造方法 * * @param field 字段 * @param propertyDescriptor 字段name对应的property */ public EntityField(Field field, PropertyDescriptor propertyDescriptor) { if (field != null) { this.field = field; this.name = field.getName(); this.javaType = field.getType(); } if (propertyDescriptor != null) { this.name = propertyDescriptor.getName(); this.setter = propertyDescriptor.getWriteMethod(); this.getter = propertyDescriptor.getReadMethod(); this.javaType = propertyDescriptor.getPropertyType(); } } /** * 先创建field,然后可以通过该方法获取property等属性 * * @param other */ public void copyFromPropertyDescriptor(EntityField other) { this.setter = other.setter; this.getter = other.getter; this.javaType = other.javaType; this.name = other.name; } /** * 是否有该注解 * * @param annotationClass * @return */ public boolean isAnnotationPresent(Class annotationClass) { boolean result = false; if (field != null) { result = field.isAnnotationPresent(annotationClass); } if (!result && setter != null) { result = setter.isAnnotationPresent(annotationClass); } if (!result && getter != null) { result = getter.isAnnotationPresent(annotationClass); } return result; } /** * 获取指定的注解 * * @param annotationClass * @param * @return */ public T getAnnotation(Class annotationClass) { T result = null; if (field != null) { result = field.getAnnotation(annotationClass); } if (result == null && setter != null) { result = setter.getAnnotation(annotationClass); } if (result == null && getter != null) { result = getter.getAnnotation(annotationClass); } return result; } /** * 反射获取值 * * @param object * @return * @throws IllegalAccessException * @throws InvocationTargetException */ public Object getValue(Object object) throws IllegalAccessException, InvocationTargetException { Object result = null; if (getter != null) { result = getter.invoke(object); } else if (field != null) { if (!field.isAccessible()) { field.setAccessible(true); } result = field.get(object); } return result; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EntityField that = (EntityField) o; return !(name != null ? !name.equals(that.name) : that.name != null); } @Override public int hashCode() { return name != null ? name.hashCode() : 0; } /** * 获取javaType * * @return */ public Class getJavaType() { return javaType; } /** * 设置javaType * * @param javaType */ public void setJavaType(Class javaType) { this.javaType = javaType; } /** * 字段属性名 * * @return */ public String getName() { return name; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/EntityTable.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; import org.apache.ibatis.mapping.ResultFlag; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.TypeException; import org.apache.ibatis.type.TypeHandler; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.util.StringUtil; import jakarta.persistence.Table; import java.lang.reflect.Constructor; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 数据库表 * * @author liuzh */ public class EntityTable { public static final Pattern DELIMITER = Pattern.compile("^[`\\[\"]?(.*?)[`\\]\"]?$"); //属性和列对应 protected Map propertyMap; private String name; private String catalog; private String schema; private String orderByClause; private String baseSelect; //实体类 => 全部列属性 private LinkedHashSet entityClassColumns; //实体类 => 主键信息 private LinkedHashSet entityClassPKColumns; //useGenerator包含多列的时候需要用到 private List keyProperties; private List keyColumns; //resultMap对象 private ResultMap resultMap; //类 private Class entityClass; public EntityTable(Class entityClass) { this.entityClass = entityClass; } /** * 生成当前实体的resultMap对象 * * @param configuration * @return */ public ResultMap getResultMap(Configuration configuration) { if (this.resultMap != null) { return this.resultMap; } if (entityClassColumns == null || entityClassColumns.size() == 0) { return null; } List resultMappings = new ArrayList(); for (EntityColumn entityColumn : entityClassColumns) { String column = entityColumn.getColumn(); //去掉可能存在的分隔符 Matcher matcher = DELIMITER.matcher(column); if (matcher.find()) { column = matcher.group(1); } ResultMapping.Builder builder = new ResultMapping.Builder(configuration, entityColumn.getProperty(), column, entityColumn.getJavaType()); if (entityColumn.getJdbcType() != null) { builder.jdbcType(entityColumn.getJdbcType()); } if (entityColumn.getTypeHandler() != null) { try { builder.typeHandler(getInstance(entityColumn.getJavaType(), entityColumn.getTypeHandler())); } catch (Exception e) { throw new MapperException(e); } } List flags = new ArrayList(); if (entityColumn.isId()) { flags.add(ResultFlag.ID); } builder.flags(flags); resultMappings.add(builder.build()); } ResultMap.Builder builder = new ResultMap.Builder(configuration, "BaseMapperResultMap", this.entityClass, resultMappings, true); this.resultMap = builder.build(); return this.resultMap; } /** * 初始化 - Example 会使用 */ public void initPropertyMap() { propertyMap = new HashMap(getEntityClassColumns().size()); for (EntityColumn column : getEntityClassColumns()) { propertyMap.put(column.getProperty(), column); } } /** * 实例化TypeHandler * * @param javaTypeClass * @param typeHandlerClass * @return */ @SuppressWarnings("unchecked") public TypeHandler getInstance(Class javaTypeClass, Class typeHandlerClass) { if (javaTypeClass != null) { try { Constructor c = typeHandlerClass.getConstructor(Class.class); return (TypeHandler) c.newInstance(javaTypeClass); } catch (NoSuchMethodException ignored) { // ignored } catch (Exception e) { throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e); } } try { Constructor c = typeHandlerClass.getConstructor(); return (TypeHandler) c.newInstance(); } catch (Exception e) { throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e); } } public String getBaseSelect() { return baseSelect; } public void setBaseSelect(String baseSelect) { this.baseSelect = baseSelect; } public String getCatalog() { return catalog; } public void setCatalog(String catalog) { this.catalog = catalog; } public Class getEntityClass() { return entityClass; } public LinkedHashSet getEntityClassColumns() { return entityClassColumns; } public void setEntityClassColumns(LinkedHashSet entityClassColumns) { this.entityClassColumns = entityClassColumns; } public LinkedHashSet getEntityClassPKColumns() { return entityClassPKColumns; } public void setEntityClassPKColumns(LinkedHashSet entityClassPKColumns) { this.entityClassPKColumns = entityClassPKColumns; } public String[] getKeyColumns() { if (keyColumns != null && keyColumns.size() > 0) { return keyColumns.toArray(new String[]{}); } return new String[]{}; } public void setKeyColumns(String keyColumn) { if (this.keyColumns == null) { this.keyColumns = new ArrayList(); this.keyColumns.add(keyColumn); } else { this.keyColumns.add(keyColumn); } } public String[] getKeyProperties() { if (keyProperties != null && keyProperties.size() > 0) { return keyProperties.toArray(new String[]{}); } return new String[]{}; } public void setKeyProperties(String keyProperty) { if (this.keyProperties == null) { this.keyProperties = new ArrayList(); this.keyProperties.add(keyProperty); } else { this.keyProperties.add(keyProperty); } } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getOrderByClause() { return orderByClause; } public void setOrderByClause(String orderByClause) { this.orderByClause = orderByClause; } public String getPrefix() { if (StringUtil.isNotEmpty(catalog)) { return catalog; } if (StringUtil.isNotEmpty(schema)) { return schema; } return ""; } public Map getPropertyMap() { return propertyMap; } public String getSchema() { return schema; } public void setSchema(String schema) { this.schema = schema; } public void setKeyColumns(List keyColumns) { this.keyColumns = keyColumns; } public void setKeyProperties(List keyProperties) { this.keyProperties = keyProperties; } public void setTable(Table table) { this.name = table.name(); this.catalog = table.catalog(); this.schema = table.schema(); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/Example.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; import org.apache.ibatis.reflection.MetaObject; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.util.MetaObjectUtil; import tk.mybatis.mapper.util.Sqls; import tk.mybatis.mapper.util.StringUtil; import java.util.*; /** * 通用的Example查询对象 * * @author liuzh */ public class Example implements IDynamicTableName { protected String orderByClause; protected boolean distinct; protected boolean exists; protected boolean notNull; protected boolean forUpdate; //查询字段 protected Set selectColumns; //排除的查询字段 protected Set excludeColumns; protected String countColumn; protected List oredCriteria; protected Class entityClass; protected EntityTable table; //属性和列对应 protected Map propertyMap; //动态表名 protected String tableName; protected OrderBy ORDERBY; /** * 默认exists为true * * @param entityClass */ public Example(Class entityClass) { this(entityClass, true); } /** * 带exists参数的构造方法,默认notNull为false,允许为空 * * @param entityClass * @param exists - true时,如果字段不存在就抛出异常,false时,如果不存在就不使用该字段的条件 */ public Example(Class entityClass, boolean exists) { this(entityClass, exists, false); } /** * 带exists参数的构造方法 * * @param entityClass * @param exists - true时,如果字段不存在就抛出异常,false时,如果不存在就不使用该字段的条件 * @param notNull - true时,如果值为空,就会抛出异常,false时,如果为空就不使用该字段的条件 */ public Example(Class entityClass, boolean exists, boolean notNull) { this.exists = exists; this.notNull = notNull; oredCriteria = new ArrayList(); this.entityClass = entityClass; table = EntityHelper.getEntityTable(entityClass); //根据李领北建议修改#159 propertyMap = table.getPropertyMap(); this.ORDERBY = new OrderBy(this, propertyMap); } private Example(Builder builder) { this.exists = builder.exists; this.notNull = builder.notNull; this.distinct = builder.distinct; this.entityClass = builder.entityClass; this.propertyMap = builder.propertyMap; this.selectColumns = builder.selectColumns; this.excludeColumns = builder.excludeColumns; this.oredCriteria = builder.exampleCriterias; this.forUpdate = builder.forUpdate; this.tableName = builder.tableName; this.ORDERBY = new OrderBy(this, propertyMap); if (!StringUtil.isEmpty(builder.orderByClause.toString())) { this.orderByClause = builder.orderByClause.toString(); } } public static Builder builder(Class entityClass) { return new Builder(entityClass); } public OrderBy orderBy(String property) { this.ORDERBY.orderBy(property); return this.ORDERBY; } /** * 排除查询字段,优先级低于 selectProperties * * @param properties 属性名的可变参数 * @return */ public Example excludeProperties(String... properties) { if (properties != null && properties.length > 0) { if (this.excludeColumns == null) { this.excludeColumns = new LinkedHashSet(); } for (String property : properties) { if (propertyMap.containsKey(property)) { this.excludeColumns.add(propertyMap.get(property).getColumn()); } else { throw new MapperException("类 " + entityClass.getSimpleName() + " 不包含属性 \'" + property + "\',或该属性被@Transient注释!"); } } } return this; } /** * 指定要查询的属性列 - 这里会自动映射到表字段 * * @param properties * @return */ public Example selectProperties(String... properties) { if (properties != null && properties.length > 0) { if (this.selectColumns == null) { this.selectColumns = new LinkedHashSet(); } for (String property : properties) { if (propertyMap.containsKey(property)) { this.selectColumns.add(propertyMap.get(property).getColumn()); } else { throw new MapperException("类 " + entityClass.getSimpleName() + " 不包含属性 \'" + property + "\',或该属性被@Transient注释!"); } } } return this; } public void or(Criteria criteria) { criteria.setAndOr("or"); oredCriteria.add(criteria); } public Criteria or() { Criteria criteria = createCriteriaInternal(); criteria.setAndOr("or"); oredCriteria.add(criteria); return criteria; } public void and(Criteria criteria) { criteria.setAndOr("and"); oredCriteria.add(criteria); } public Criteria and() { Criteria criteria = createCriteriaInternal(); criteria.setAndOr("and"); oredCriteria.add(criteria); return criteria; } public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if (oredCriteria.size() == 0) { criteria.setAndOr("and"); oredCriteria.add(criteria); } return criteria; } protected Criteria createCriteriaInternal() { Criteria criteria = new Criteria(propertyMap, exists, notNull); return criteria; } public void clear() { oredCriteria.clear(); orderByClause = null; distinct = false; } public Map getPropertyMap() { return propertyMap; } public static class OrderBy { //属性和列对应 protected Map propertyMap; private Example example; private Boolean isProperty; public OrderBy(Example example, Map propertyMap) { this.example = example; this.propertyMap = propertyMap; } private String property(String property) { if (StringUtil.isEmpty(property) || StringUtil.isEmpty(property.trim())) { throw new MapperException("接收的property为空!"); } property = property.trim(); if (!propertyMap.containsKey(property)) { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } return propertyMap.get(property).getColumn(); } public OrderBy orderBy(String property) { String column = property(property); if (column == null) { isProperty = false; return this; } if (StringUtil.isNotEmpty(example.getOrderByClause())) { example.setOrderByClause(example.getOrderByClause() + "," + column); } else { example.setOrderByClause(column); } isProperty = true; return this; } public OrderBy desc() { if (isProperty) { example.setOrderByClause(example.getOrderByClause() + " DESC"); isProperty = false; } return this; } public OrderBy asc() { if (isProperty) { example.setOrderByClause(example.getOrderByClause() + " ASC"); isProperty = false; } return this; } } protected abstract static class GeneratedCriteria { protected List criteria; //字段是否必须存在 protected boolean exists; //值是否不能为空 protected boolean notNull; //连接条件 protected String andOr; //属性和列对应 protected Map propertyMap; protected GeneratedCriteria(Map propertyMap, boolean exists, boolean notNull) { super(); this.exists = exists; this.notNull = notNull; criteria = new ArrayList(); this.propertyMap = propertyMap; } private String column(String property) { if (propertyMap.containsKey(property)) { return propertyMap.get(property).getColumn(); } else if (exists) { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } else { return null; } } private String property(String property) { if (propertyMap.containsKey(property)) { return property; } else if (exists) { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } else { return null; } } protected void addCriterion(String condition) { if (condition == null) { throw new MapperException("Value for condition cannot be null"); } if (condition.startsWith("null")) { return; } criteria.add(new Criterion(condition)); } protected void addCriterion(String condition, Object value, String property) { if (value == null) { if (notNull) { throw new MapperException("Value for " + property + " cannot be null"); } else { return; } } if (property == null) { return; } criteria.add(new Criterion(condition, value)); } protected void addCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { if (notNull) { throw new MapperException("Between values for " + property + " cannot be null"); } else { return; } } if (property == null) { return; } criteria.add(new Criterion(condition, value1, value2)); } protected void addOrCriterion(String condition) { if (condition == null) { throw new MapperException("Value for condition cannot be null"); } if (condition.startsWith("null")) { return; } criteria.add(new Criterion(condition, true)); } protected void addOrCriterion(String condition, Object value, String property) { if (value == null) { if (notNull) { throw new MapperException("Value for " + property + " cannot be null"); } else { return; } } if (property == null) { return; } criteria.add(new Criterion(condition, value, true)); } protected void addOrCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { if (notNull) { throw new MapperException("Between values for " + property + " cannot be null"); } else { return; } } if (property == null) { return; } criteria.add(new Criterion(condition, value1, value2, true)); } public Criteria andIsNull(String property) { addCriterion(column(property) + " is null"); return (Criteria) this; } public Criteria andIsNotNull(String property) { addCriterion(column(property) + " is not null"); return (Criteria) this; } public Criteria andEqualTo(String property, Object value) { addCriterion(column(property) + " =", value, property(property)); return (Criteria) this; } public Criteria andNotEqualTo(String property, Object value) { addCriterion(column(property) + " <>", value, property(property)); return (Criteria) this; } public Criteria andGreaterThan(String property, Object value) { addCriterion(column(property) + " >", value, property(property)); return (Criteria) this; } public Criteria andGreaterThanOrEqualTo(String property, Object value) { addCriterion(column(property) + " >=", value, property(property)); return (Criteria) this; } public Criteria andLessThan(String property, Object value) { addCriterion(column(property) + " <", value, property(property)); return (Criteria) this; } public Criteria andLessThanOrEqualTo(String property, Object value) { addCriterion(column(property) + " <=", value, property(property)); return (Criteria) this; } public Criteria andIn(String property, Iterable values) { addCriterion(column(property) + " in", values, property(property)); return (Criteria) this; } public Criteria andNotIn(String property, Iterable values) { addCriterion(column(property) + " not in", values, property(property)); return (Criteria) this; } public Criteria andBetween(String property, Object value1, Object value2) { addCriterion(column(property) + " between", value1, value2, property(property)); return (Criteria) this; } public Criteria andNotBetween(String property, Object value1, Object value2) { addCriterion(column(property) + " not between", value1, value2, property(property)); return (Criteria) this; } public Criteria andLike(String property, String value) { addCriterion(column(property) + " like", value, property(property)); return (Criteria) this; } public Criteria andNotLike(String property, String value) { addCriterion(column(property) + " not like", value, property(property)); return (Criteria) this; } /** * 手写条件 * * @param condition 例如 "length(countryname)<5" * @return */ public Criteria andCondition(String condition) { addCriterion(condition); return (Criteria) this; } /** * 手写左边条件,右边用value值 * * @param condition 例如 "length(countryname)=" * @param value 例如 5 * @return */ public Criteria andCondition(String condition, Object value) { criteria.add(new Criterion(condition, value)); return (Criteria) this; } /** * 将此对象的不为空的字段参数作为相等查询条件 * * @param param 参数对象 * @author Bob {@link}0haizhu0@gmail.com * @Date 2015年7月17日 下午12:48:08 */ public Criteria andEqualTo(Object param) { if (param == null) { return (Criteria) this; } MetaObject metaObject = MetaObjectUtil.forObject(param); String[] properties = metaObject.getGetterNames(); for (String property : properties) { //属性和列对应Map中有此属性 if (propertyMap.get(property) != null) { Object value = metaObject.getValue(property); //属性值不为空 if (value != null) { andEqualTo(property, value); } } } return (Criteria) this; } /** * 将此对象的所有字段参数作为相等查询条件,如果字段为 null,则为 is null * * @param param 参数对象 */ public Criteria andAllEqualTo(Object param) { MetaObject metaObject = MetaObjectUtil.forObject(param); String[] properties = metaObject.getGetterNames(); for (String property : properties) { //属性和列对应Map中有此属性 if (propertyMap.get(property) != null) { Object value = metaObject.getValue(property); //属性值不为空 if (value != null) { andEqualTo(property, value); } else { andIsNull(property); } } } return (Criteria) this; } public Criteria orIsNull(String property) { addOrCriterion(column(property) + " is null"); return (Criteria) this; } public Criteria orIsNotNull(String property) { addOrCriterion(column(property) + " is not null"); return (Criteria) this; } public Criteria orEqualTo(String property, Object value) { addOrCriterion(column(property) + " =", value, property(property)); return (Criteria) this; } public Criteria orNotEqualTo(String property, Object value) { addOrCriterion(column(property) + " <>", value, property(property)); return (Criteria) this; } public Criteria orGreaterThan(String property, Object value) { addOrCriterion(column(property) + " >", value, property(property)); return (Criteria) this; } public Criteria orGreaterThanOrEqualTo(String property, Object value) { addOrCriterion(column(property) + " >=", value, property(property)); return (Criteria) this; } public Criteria orLessThan(String property, Object value) { addOrCriterion(column(property) + " <", value, property(property)); return (Criteria) this; } public Criteria orLessThanOrEqualTo(String property, Object value) { addOrCriterion(column(property) + " <=", value, property(property)); return (Criteria) this; } public Criteria orIn(String property, Iterable values) { addOrCriterion(column(property) + " in", values, property(property)); return (Criteria) this; } public Criteria orNotIn(String property, Iterable values) { addOrCriterion(column(property) + " not in", values, property(property)); return (Criteria) this; } public Criteria orBetween(String property, Object value1, Object value2) { addOrCriterion(column(property) + " between", value1, value2, property(property)); return (Criteria) this; } public Criteria orNotBetween(String property, Object value1, Object value2) { addOrCriterion(column(property) + " not between", value1, value2, property(property)); return (Criteria) this; } public Criteria orLike(String property, String value) { addOrCriterion(column(property) + " like", value, property(property)); return (Criteria) this; } public Criteria orNotLike(String property, String value) { addOrCriterion(column(property) + " not like", value, property(property)); return (Criteria) this; } /** * 手写条件 * * @param condition 例如 "length(countryname)<5" * @return */ public Criteria orCondition(String condition) { addOrCriterion(condition); return (Criteria) this; } /** * 手写左边条件,右边用value值 * * @param condition 例如 "length(countryname)=" * @param value 例如 5 * @return */ public Criteria orCondition(String condition, Object value) { criteria.add(new Criterion(condition, value, true)); return (Criteria) this; } /** * 将此对象的不为空的字段参数作为相等查询条件 * * @param param 参数对象 * @author Bob {@link}0haizhu0@gmail.com * @Date 2015年7月17日 下午12:48:08 */ public Criteria orEqualTo(Object param) { MetaObject metaObject = MetaObjectUtil.forObject(param); String[] properties = metaObject.getGetterNames(); for (String property : properties) { //属性和列对应Map中有此属性 if (propertyMap.get(property) != null) { Object value = metaObject.getValue(property); //属性值不为空 if (value != null) { orEqualTo(property, value); } } } return (Criteria) this; } /** * 将此对象的所有字段参数作为相等查询条件,如果字段为 null,则为 is null * * @param param 参数对象 */ public Criteria orAllEqualTo(Object param) { MetaObject metaObject = MetaObjectUtil.forObject(param); String[] properties = metaObject.getGetterNames(); for (String property : properties) { //属性和列对应Map中有此属性 if (propertyMap.get(property) != null) { Object value = metaObject.getValue(property); //属性值不为空 if (value != null) { orEqualTo(property, value); } else { orIsNull(property); } } } return (Criteria) this; } public List getAllCriteria() { return criteria; } public String getAndOr() { return andOr; } public void setAndOr(String andOr) { this.andOr = andOr; } public List getCriteria() { return criteria; } public boolean isValid() { if (criteria.size() == 0) { return false; } if (notNull) { return true; } for (Criterion criterion : criteria) { if (criterion.isValid()) { return true; } } return false; } } public static class Criteria extends GeneratedCriteria { protected Criteria(Map propertyMap, boolean exists, boolean notNull) { super(propertyMap, exists, notNull); } } public static class Criterion { private String condition; private Object value; private Object secondValue; private String andOr; private boolean noValue; private boolean singleValue; private boolean betweenValue; private boolean listValue; private String typeHandler; protected Criterion(String condition) { this(condition, false); } protected Criterion(String condition, Object value, String typeHandler) { this(condition, value, typeHandler, false); } protected Criterion(String condition, Object value) { this(condition, value, null, false); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { this(condition, value, secondValue, typeHandler, false); } protected Criterion(String condition, Object value, Object secondValue) { this(condition, value, secondValue, null, false); } protected Criterion(String condition, boolean isOr) { super(); this.condition = condition; this.typeHandler = null; this.noValue = true; this.andOr = isOr ? "or" : "and"; } protected Criterion(String condition, Object value, String typeHandler, boolean isOr) { super(); this.condition = condition; this.value = value; this.typeHandler = typeHandler; this.andOr = isOr ? "or" : "and"; if (value instanceof Collection) { this.listValue = true; } else { this.singleValue = true; } } protected Criterion(String condition, Object value, boolean isOr) { this(condition, value, null, isOr); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler, boolean isOr) { super(); this.condition = condition; this.value = value; this.secondValue = secondValue; this.typeHandler = typeHandler; this.betweenValue = true; this.andOr = isOr ? "or" : "and"; } protected Criterion(String condition, Object value, Object secondValue, boolean isOr) { this(condition, value, secondValue, null, isOr); } public String getAndOr() { return andOr; } public void setAndOr(String andOr) { this.andOr = andOr; } public String getCondition() { return condition; } public Object getSecondValue() { return secondValue; } public String getTypeHandler() { return typeHandler; } public Object getValue() { return value; } public boolean isBetweenValue() { return betweenValue; } public boolean isListValue() { return listValue; } public boolean isNoValue() { return noValue; } public boolean isSingleValue() { return singleValue; } public boolean isValid() { if (noValue) { return true; } if (singleValue) { return value != null; } if (betweenValue) { return value != null && secondValue != null; } if (listValue) { return value != null; } return false; } } public static class Builder { private final Class entityClass; protected EntityTable table; //属性和列对应 protected Map propertyMap; private StringBuilder orderByClause; private boolean distinct; private boolean exists; private boolean notNull; private boolean forUpdate; //查询字段 private Set selectColumns; //排除的查询字段 private Set excludeColumns; private String countColumn; private List sqlsCriteria; //动态表名 private List exampleCriterias; //动态表名 private String tableName; public Builder(Class entityClass) { this(entityClass, true); } public Builder(Class entityClass, boolean exists) { this(entityClass, exists, false); } public Builder(Class entityClass, boolean exists, boolean notNull) { this.entityClass = entityClass; this.exists = exists; this.notNull = notNull; this.orderByClause = new StringBuilder(); this.table = EntityHelper.getEntityTable(entityClass); this.propertyMap = table.getPropertyMap(); this.sqlsCriteria = new ArrayList(2); } public Builder distinct() { return setDistinct(true); } public Builder forUpdate() { return setForUpdate(true); } public Builder selectDistinct(String... properties) { select(properties); this.distinct = true; return this; } public Builder select(String... properties) { if (properties != null && properties.length > 0) { if (this.selectColumns == null) { this.selectColumns = new LinkedHashSet(); } for (String property : properties) { if (this.propertyMap.containsKey(property)) { this.selectColumns.add(propertyMap.get(property).getColumn()); } else { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } } } return this; } public Builder notSelect(String... properties) { if (properties != null && properties.length > 0) { if (this.excludeColumns == null) { this.excludeColumns = new LinkedHashSet(); } for (String property : properties) { if (propertyMap.containsKey(property)) { this.excludeColumns.add(propertyMap.get(property).getColumn()); } else { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } } } return this; } public Builder from(String tableName) { return setTableName(tableName); } public Builder where(Sqls sqls) { Sqls.Criteria criteria = sqls.getCriteria(); criteria.setAndOr("and"); this.sqlsCriteria.add(criteria); return this; } public Builder where(SqlsCriteria sqls) { Sqls.Criteria criteria = sqls.getCriteria(); criteria.setAndOr("and"); this.sqlsCriteria.add(criteria); return this; } public Builder andWhere(Sqls sqls) { Sqls.Criteria criteria = sqls.getCriteria(); criteria.setAndOr("and"); this.sqlsCriteria.add(criteria); return this; } public Builder andWhere(SqlsCriteria sqls) { Sqls.Criteria criteria = sqls.getCriteria(); criteria.setAndOr("and"); this.sqlsCriteria.add(criteria); return this; } public Builder orWhere(Sqls sqls) { Sqls.Criteria criteria = sqls.getCriteria(); criteria.setAndOr("or"); this.sqlsCriteria.add(criteria); return this; } public Builder orWhere(SqlsCriteria sqls) { Sqls.Criteria criteria = sqls.getCriteria(); criteria.setAndOr("or"); this.sqlsCriteria.add(criteria); return this; } public Builder orderBy(String... properties) { return orderByAsc(properties); } public Builder orderByAsc(String... properties) { contactOrderByClause(" Asc", properties); return this; } public Builder orderByDesc(String... properties) { contactOrderByClause(" Desc", properties); return this; } private void contactOrderByClause(String order, String... properties) { StringBuilder columns = new StringBuilder(); for (String property : properties) { String column; if ((column = propertyforOderBy(property)) != null) { columns.append(",").append(column).append(order); } } ; if (columns.length() > 0) { orderByClause.append(columns); } } public Example build() { this.exampleCriterias = new ArrayList(); for (Sqls.Criteria criteria : sqlsCriteria) { Example.Criteria exampleCriteria = new Example.Criteria(this.propertyMap, this.exists, this.notNull); exampleCriteria.setAndOr(criteria.getAndOr()); for (Sqls.Criterion criterion : criteria.getCriterions()) { String condition = criterion.getCondition(); String andOr = criterion.getAndOr(); String property = criterion.getProperty(); Object[] values = criterion.getValues(); transformCriterion(exampleCriteria, condition, property, values, andOr); } exampleCriterias.add(exampleCriteria); } if (this.orderByClause.length() > 0) { this.orderByClause = new StringBuilder(this.orderByClause.substring(1, this.orderByClause.length())); } return new Example(this); } private void transformCriterion(Example.Criteria exampleCriteria, String condition, String property, Object[] values, String andOr) { if (values.length == 0) { if ("and".equals(andOr)) { exampleCriteria.addCriterion(column(property) + " " + condition); } else { exampleCriteria.addOrCriterion(column(property) + " " + condition); } } else if (values.length == 1) { if ("and".equals(andOr)) { exampleCriteria.addCriterion(column(property) + " " + condition, values[0], property(property)); } else { exampleCriteria.addOrCriterion(column(property) + " " + condition, values[0], property(property)); } } else if (values.length == 2) { if ("and".equals(andOr)) { exampleCriteria.addCriterion(column(property) + " " + condition, values[0], values[1], property(property)); } else { exampleCriteria.addOrCriterion(column(property) + " " + condition, values[0], values[1], property(property)); } } } private String column(String property) { if (propertyMap.containsKey(property)) { return propertyMap.get(property).getColumn(); } else if (exists) { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } else { return null; } } private String property(String property) { if (propertyMap.containsKey(property)) { return property; } else if (exists) { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } else { return null; } } private String propertyforOderBy(String property) { if (StringUtil.isEmpty(property) || StringUtil.isEmpty(property.trim())) { throw new MapperException("接收的property为空!"); } property = property.trim(); if (!propertyMap.containsKey(property)) { throw new MapperException("当前实体类不包含名为" + property + "的属性!"); } return propertyMap.get(property).getColumn(); } public Builder setDistinct(boolean distinct) { this.distinct = distinct; return this; } public Builder setForUpdate(boolean forUpdate) { this.forUpdate = forUpdate; return this; } public Builder setTableName(String tableName) { this.tableName = tableName; return this; } } public String getCountColumn() { return countColumn; } @Override public String getDynamicTableName() { return tableName; } public Class getEntityClass() { return entityClass; } public String getOrderByClause() { return orderByClause; } public void setOrderByClause(String orderByClause) { this.orderByClause = orderByClause; } public List getOredCriteria() { return oredCriteria; } public Set getSelectColumns() { if (selectColumns != null && selectColumns.size() > 0) { //不需要处理 } else if (excludeColumns != null && excludeColumns.size() > 0) { Collection entityColumns = propertyMap.values(); selectColumns = new LinkedHashSet(entityColumns.size() - excludeColumns.size()); for (EntityColumn column : entityColumns) { if (!excludeColumns.contains(column.getColumn())) { selectColumns.add(column.getColumn()); } } } return selectColumns; } public boolean isDistinct() { return distinct; } public void setDistinct(boolean distinct) { this.distinct = distinct; } public boolean isForUpdate() { return forUpdate; } public void setForUpdate(boolean forUpdate) { this.forUpdate = forUpdate; } /** * 指定 count(property) 查询属性 * * @param property */ public void setCountProperty(String property) { if (propertyMap.containsKey(property)) { this.countColumn = propertyMap.get(property).getColumn(); } } /** * 设置表名 * * @param tableName */ public void setTableName(String tableName) { this.tableName = tableName; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/IDynamicTableName.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; /** * 实现动态表名时,实体类需要实现该接口 * * @author liuzh * @since 2015-10-28 22:20 */ public interface IDynamicTableName { /** * 获取动态表名 - 只要有返回值,不是null和'',就会用返回值作为表名 * * @return */ String getDynamicTableName(); } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/entity/SqlsCriteria.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.entity; import tk.mybatis.mapper.util.Sqls; /** * @author liuzh */ public interface SqlsCriteria { Sqls.Criteria getCriteria(); } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/genid/GenId.java ================================================ package tk.mybatis.mapper.genid; /** * 不提供具体的实现,这里提供一个思路。
*

* 在 Spring 集成环境中,可以通过配置静态方式获取 Spring 的 context 对象。
*

* 如果使用 vesta(https://gitee.com/free/vesta-id-generator) 来生成 ID,假设已经提供了 vesta 的 idService。
*

* 那么可以在实现中获取该类,然后生成 Id 返回,示例代码如下: * *

 * public class VestaGenId implement GenId {
 *    public Long genId(String table, String column){
 *        //ApplicationUtil.getBean 需要自己实现
 *        IdService idService = ApplicationUtil.getBean(IdService.class);
 *        return idService.genId();
 *    }
 * }
 * 
* * @author liuzh */ public interface GenId { T genId(String table, String column); class NULL implements GenId { @Override public Object genId(String table, String column) { throw new UnsupportedOperationException(); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/genid/GenIdUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.genid; import org.apache.ibatis.reflection.MetaObject; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.util.MetaObjectUtil; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; /** * @author liuzh * @since 2018-04-22 */ public class GenIdUtil { public static final Map, GenId> CACHE = new ConcurrentHashMap, GenId>(); public static final ReentrantLock LOCK = new ReentrantLock(); /** * 生成 Id * * @param target * @param property * @param genClass * @param table * @param column * @throws MapperException */ public static void genId(Object target, String property, Class genClass, String table, String column) throws MapperException { try { GenId genId; if (CACHE.containsKey(genClass)) { genId = CACHE.get(genClass); } else { LOCK.lock(); try { if (!CACHE.containsKey(genClass)) { CACHE.put(genClass, genClass.newInstance()); } genId = CACHE.get(genClass); } finally { LOCK.unlock(); } } MetaObject metaObject = MetaObjectUtil.forObject(target); if (metaObject.getValue(property) == null) { Object id = genId.genId(table, column); metaObject.setValue(property, id); } } catch (Exception e) { throw new MapperException("生成 ID 失败!", e); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/gensql/GenSql.java ================================================ package tk.mybatis.mapper.gensql; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; /** * 生成 SQL,初始化时执行 * * @author liuzh */ public interface GenSql { String genSql(EntityTable entityTable, EntityColumn entityColumn); class NULL implements GenSql { @Override public String genSql(EntityTable entityTable, EntityColumn entityColumn) { throw new UnsupportedOperationException(); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/EntityHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.resolve.DefaultEntityResolve; import tk.mybatis.mapper.mapperhelper.resolve.EntityResolve; import tk.mybatis.mapper.util.MetaObjectUtil; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * 实体类工具类 - 处理实体和数据库表以及字段关键的一个类 *

*

项目地址 : https://github.com/abel533/Mapper

* * @author liuzh */ public class EntityHelper { /** * 实体类 => 表对象 */ private static final Map, EntityTable> entityTableMap = new ConcurrentHashMap, EntityTable>(); private static final EntityResolve DEFAULT = new DefaultEntityResolve(); /** * 实体类解析器 */ private static EntityResolve resolve = DEFAULT; /** * 获取表对象 * * @param entityClass * @return */ public static EntityTable getEntityTable(Class entityClass) { EntityTable entityTable = entityTableMap.get(entityClass); if (entityTable == null) { throw new MapperException("无法获取实体类" + entityClass.getName() + "对应的表名!"); } return entityTable; } /** * 获取表对象,如果没有则返回Null * * @param entityClass * @return */ public static EntityTable getEntityTableOrNull(Class entityClass) { return entityTableMap.get(entityClass); } /** * 获取默认的orderby语句 * * @param entityClass * @return */ public static String getOrderByClause(Class entityClass) { EntityTable table = getEntityTable(entityClass); if (table.getOrderByClause() != null) { return table.getOrderByClause(); } List orderEntityColumns = new ArrayList(); for (EntityColumn column : table.getEntityClassColumns()) { if (column.getOrderBy() != null) { orderEntityColumns.add(column); } } Collections.sort(orderEntityColumns, new Comparator() { @Override public int compare(EntityColumn o1, EntityColumn o2) { return o1.getOrderPriority() - o2.getOrderPriority(); } }); StringBuilder orderBy = new StringBuilder(); for (EntityColumn column : orderEntityColumns) { if (orderBy.length() != 0) { orderBy.append(","); } orderBy.append(column.getColumn()).append(" ").append(column.getOrderBy()); } table.setOrderByClause(orderBy.toString()); return table.getOrderByClause(); } /** * 获取全部列 * * @param entityClass * @return */ public static Set getColumns(Class entityClass) { return getEntityTable(entityClass).getEntityClassColumns(); } /** * 获取主键信息 * * @param entityClass * @return */ public static Set getPKColumns(Class entityClass) { return getEntityTable(entityClass).getEntityClassPKColumns(); } /** * 获取查询的Select * * @param entityClass * @return */ public static String getSelectColumns(Class entityClass) { EntityTable entityTable = getEntityTable(entityClass); if (entityTable.getBaseSelect() != null) { return entityTable.getBaseSelect(); } Set columnList = getColumns(entityClass); StringBuilder selectBuilder = new StringBuilder(); boolean skipAlias = Map.class.isAssignableFrom(entityClass); for (EntityColumn entityColumn : columnList) { selectBuilder.append(entityColumn.getColumn()); if (!skipAlias && !entityColumn.getColumn().equalsIgnoreCase(entityColumn.getProperty())) { //不等的时候分几种情况,例如`DESC` if (entityColumn.getColumn().substring(1, entityColumn.getColumn().length() - 1).equalsIgnoreCase(entityColumn.getProperty())) { selectBuilder.append(","); } else { selectBuilder.append(" AS ").append(entityColumn.getProperty()).append(","); } } else { selectBuilder.append(","); } } entityTable.setBaseSelect(selectBuilder.substring(0, selectBuilder.length() - 1)); return entityTable.getBaseSelect(); } /** * 初始化实体属性 * * @param entityClass * @param config */ public static synchronized void initEntityNameMap(Class entityClass, Config config) { if (entityTableMap.get(entityClass) != null) { return; } //创建并缓存EntityTable EntityTable entityTable = resolve.resolveEntity(entityClass, config); entityTableMap.put(entityClass, entityTable); } /** * 设置实体类解析器 * * @param resolve */ static void setResolve(EntityResolve resolve) { EntityHelper.resolve = resolve; } /** * 通过反射设置MappedStatement的keyProperties字段值 * * @param pkColumns 所有的主键字段 * @param ms MappedStatement */ public static void setKeyProperties(Set pkColumns, MappedStatement ms) { if (pkColumns == null || pkColumns.isEmpty()) { return; } List keyProperties = new ArrayList(pkColumns.size()); for (EntityColumn column : pkColumns) { keyProperties.add(column.getProperty()); } MetaObjectUtil.forObject(ms).setValue("keyProperties", keyProperties.toArray(new String[]{})); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/FieldHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityField; import jakarta.persistence.Entity; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; /** * 类字段工具类 * * @author liuzh * @since 2015-12-06 18:38 */ public class FieldHelper { private static final IFieldHelper fieldHelper = new Jdk8FieldHelper(); /** * 获取全部的Field * * @param entityClass * @return */ public static List getFields(Class entityClass) { return fieldHelper.getFields(entityClass); } /** * 获取全部的属性,通过方法名获取 * * @param entityClass * @return */ public static List getProperties(Class entityClass) { return fieldHelper.getProperties(entityClass); } /** * 获取全部的属性,包含字段和方法 * * @param entityClass * @return * @throws IntrospectionException */ public static List getAll(Class entityClass) { List fields = fieldHelper.getFields(entityClass); List properties = fieldHelper.getProperties(entityClass); //拼到一起,名字相同的合并 List all = new ArrayList(); Set usedSet = new HashSet(); for (EntityField field : fields) { for (EntityField property : properties) { if (!usedSet.contains(property) && field.getName().equals(property.getName())) { field.copyFromPropertyDescriptor(property); usedSet.add(property); break; } } all.add(field); } for (EntityField property : properties) { if (!usedSet.contains(property)) { all.add(property); } } return all; } /** * 判断是否已经包含同名的field * * @param fieldList * @param filedName * @return */ private static boolean containFiled(List fieldList, String filedName) { for (EntityField field : fieldList) { if (field.getName().equals(filedName)) { return true; } } return false; } /** * Field接口 */ interface IFieldHelper { /** * 获取全部的Field * * @param entityClass * @return */ List getFields(Class entityClass); /** * 获取全部的属性,通过方法名获取 * * @param entityClass * @return */ List getProperties(Class entityClass); } /** * 支持jdk8 */ static class Jdk8FieldHelper implements IFieldHelper { /** * 获取全部的Field * * @param entityClass * @return */ @Override public List getFields(Class entityClass) { List fields = _getFields(entityClass, null, null); fields = new ArrayList(new LinkedHashSet(fields)); List properties = getProperties(entityClass); Set usedSet = new HashSet(); for (EntityField field : fields) { for (EntityField property : properties) { if (!usedSet.contains(property) && field.getName().equals(property.getName())) { //泛型的情况下通过属性可以得到实际的类型 field.setJavaType(property.getJavaType()); break; } } } return fields; } /** * 获取全部的Field,仅仅通过Field获取 * * @param entityClass * @param fieldList * @param level * @return */ private List _getFields(Class entityClass, List fieldList, Integer level) { if (fieldList == null) { fieldList = new ArrayList(); } if (level == null) { level = 0; } if (entityClass.equals(Object.class)) { return fieldList; } Field[] fields = entityClass.getDeclaredFields(); Arrays.sort(fields, Comparator.comparing(Field::getName)); int index = 0; for (int i = 0; i < fields.length; i++) { Field field = fields[i]; //排除静态字段,解决bug#2 if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isTransient(field.getModifiers())) { //如果父类中包含与子类同名field,则跳过处理,允许子类进行覆盖 if (FieldHelper.containFiled(fieldList, field.getName())) { continue; } if (level.intValue() != 0) { //将父类的字段放在前面 fieldList.add(index, new EntityField(field, null)); index++; } else { fieldList.add(new EntityField(field, null)); } } } Class superClass = entityClass.getSuperclass(); if (superClass != null && !superClass.equals(Object.class) && (superClass.isAnnotationPresent(Entity.class) || (!Map.class.isAssignableFrom(superClass) && !Collection.class.isAssignableFrom(superClass)))) { return _getFields(entityClass.getSuperclass(), fieldList, ++level); } return fieldList; } /** * 通过方法获取属性 * * @param entityClass * @return */ @Override public List getProperties(Class entityClass) { List entityFields = new ArrayList(); BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo(entityClass); } catch (IntrospectionException e) { throw new MapperException(e); } PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor desc : descriptors) { if (!"class".equals(desc.getName())) { entityFields.add(new EntityField(null, desc)); } } return entityFields; } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/MapperHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.annotations.UpdateProvider; import org.apache.ibatis.builder.annotation.ProviderSqlSource; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.scripting.defaults.RawSqlSource; import org.apache.ibatis.session.Configuration; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.resolve.EntityResolve; import tk.mybatis.mapper.provider.EmptyProvider; import tk.mybatis.mapper.util.MetaObjectUtil; import tk.mybatis.mapper.util.StringUtil; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import static tk.mybatis.mapper.util.MsUtil.getMapperClass; /** * 处理主要逻辑,最关键的一个类 *

*

项目地址 : https://github.com/abel533/Mapper

* * @author liuzh */ public class MapperHelper { private static final Log log = LogFactory.getLog(MapperHelper.class); /** * 注册的接口 */ private List> registerClass = new ArrayList>(); /** * 注册的通用Mapper接口 */ private Map, Collection> registerMapper = new ConcurrentHashMap, Collection>(); /** * 通用Mapper配置 */ private Config config = new Config(); /** * 默认构造方法 */ public MapperHelper() { } /** * 带配置的构造方法 * * @param properties */ public MapperHelper(Properties properties) { this(); setProperties(properties); } /** * 通过通用Mapper接口获取对应的MapperTemplate * * @param mapperClass * @return * @throws Exception */ private Collection fromMapperClasses(Class mapperClass) { Map, MapperTemplate> templateMap = new ConcurrentHashMap, MapperTemplate>(); Method[] methods = mapperClass.getDeclaredMethods(); for (Method method : methods) { Class templateClass = null; if (method.isAnnotationPresent(SelectProvider.class)) { SelectProvider provider = method.getAnnotation(SelectProvider.class); templateClass = provider.type(); } else if (method.isAnnotationPresent(InsertProvider.class)) { InsertProvider provider = method.getAnnotation(InsertProvider.class); templateClass = provider.type(); } else if (method.isAnnotationPresent(DeleteProvider.class)) { DeleteProvider provider = method.getAnnotation(DeleteProvider.class); templateClass = provider.type(); } else if (method.isAnnotationPresent(UpdateProvider.class)) { UpdateProvider provider = method.getAnnotation(UpdateProvider.class); templateClass = provider.type(); } if (templateClass == null || !MapperTemplate.class.isAssignableFrom(templateClass)) { templateClass = EmptyProvider.class; } MapperTemplate mapperTemplate; try { mapperTemplate = templateMap.getOrDefault(templateClass, (MapperTemplate) templateClass.getConstructor(Class.class, MapperHelper.class).newInstance(mapperClass, this)); templateMap.put(templateClass, mapperTemplate); } catch (Exception e) { log.error("实例化MapperTemplate对象失败:" + e, e); throw new MapperException("实例化MapperTemplate对象失败:" + e.getMessage()); } //注册方法 try { mapperTemplate.addMethodMap(method.getName(), templateClass.getMethod(method.getName(), MappedStatement.class)); } catch (NoSuchMethodException e) { log.error(templateClass.getName() + "中缺少" + method.getName() + "方法!", e); throw new MapperException(templateClass.getName() + "中缺少" + method.getName() + "方法!"); } } return templateMap.values(); } /** * 注册通用Mapper接口 * * @param mapperClass */ public void registerMapper(Class mapperClass) { if (!registerMapper.containsKey(mapperClass)) { registerClass.add(mapperClass); registerMapper.put(mapperClass, fromMapperClasses(mapperClass)); } //自动注册继承的接口 Class[] interfaces = mapperClass.getInterfaces(); if (interfaces != null && interfaces.length > 0) { for (Class anInterface : interfaces) { registerMapper(anInterface); } } } /** * 注册通用Mapper接口 * * @param mapperClass */ public void registerMapper(String mapperClass) { try { registerMapper(Class.forName(mapperClass)); } catch (ClassNotFoundException e) { log.error("注册通用Mapper[" + mapperClass + "]失败,找不到该通用Mapper!", e); throw new MapperException("注册通用Mapper[" + mapperClass + "]失败,找不到该通用Mapper!"); } } /** * 判断当前的接口方法是否需要进行拦截 * * @param msId * @return */ public MapperTemplate isMapperMethod(String msId) { MapperTemplate mapperTemplate = getMapperTemplateByMsId(msId); if (mapperTemplate == null) { //通过 @RegisterMapper 注解自动注册的功能 try { Class mapperClass = getMapperClass(msId); if (mapperClass.isInterface() && hasRegisterMapper(mapperClass)) { mapperTemplate = getMapperTemplateByMsId(msId); } } catch (Exception e) { log.warn("特殊情况: " + e); } } return mapperTemplate; } /** * 根据 msId 获取 MapperTemplate * * @param msId * @return */ public MapperTemplate getMapperTemplateByMsId(String msId) { for (Map.Entry, Collection> entry : registerMapper.entrySet()) { for (MapperTemplate t : entry.getValue()) { if (t.supportMethod(msId)) { return t; } } } return null; } /** * 判断接口是否包含通用接口, * * @param mapperInterface * @return */ public boolean isExtendCommonMapper(Class mapperInterface) { for (Class mapperClass : registerClass) { if (mapperClass.isAssignableFrom(mapperInterface)) { return true; } } //通过 @RegisterMapper 注解自动注册的功能 return hasRegisterMapper(mapperInterface); } /** * 增加通过 @RegisterMapper 注解自动注册的功能 * * @param mapperInterface * @return */ private boolean hasRegisterMapper(Class mapperInterface) { //如果一个都没匹配上,很可能是还没有注册 mappers,此时通过 @RegisterMapper 注解进行判断 Class[] interfaces = mapperInterface.getInterfaces(); boolean hasRegisterMapper = false; if (interfaces != null && interfaces.length > 0) { for (Class anInterface : interfaces) { //自动注册标记了 @RegisterMapper 的接口 if (anInterface.isAnnotationPresent(RegisterMapper.class)) { hasRegisterMapper = true; //如果已经注册过,就避免在反复调用下面会迭代的方法 if (!registerMapper.containsKey(anInterface)) { registerMapper(anInterface); } } //如果父接口的父接口存在注解,也可以注册 else if (hasRegisterMapper(anInterface)) { hasRegisterMapper = true; } } } return hasRegisterMapper; } /** * 配置完成后,执行下面的操作 *
处理configuration中全部的MappedStatement * * @param configuration */ public void processConfiguration(Configuration configuration) { processConfiguration(configuration, null); } /** * 配置指定的接口 * * @param configuration * @param mapperInterface */ public void processConfiguration(Configuration configuration, Class mapperInterface) { String prefix; if (mapperInterface != null) { prefix = mapperInterface.getName(); } else { prefix = ""; } for (Object object : new ArrayList(configuration.getMappedStatements())) { if (object instanceof MappedStatement) { MappedStatement ms = (MappedStatement) object; if (ms.getId().startsWith(prefix)) { processMappedStatement(ms); } } } } /** * 处理 MappedStatement * * @param ms */ public void processMappedStatement(MappedStatement ms) { MapperTemplate mapperTemplate = isMapperMethod(ms.getId()); if (mapperTemplate != null && ms.getSqlSource() instanceof ProviderSqlSource) { setSqlSource(ms, mapperTemplate); } // 如果是原生mybatisSqlSource的查询,添加ResultMap if (config.isEnableBaseResultMapFlag() && ms.getSqlSource() instanceof RawSqlSource && ms.getSqlCommandType() == SqlCommandType.SELECT) { if (ms.getResultMaps() != null && !ms.getResultMaps().isEmpty()) { setRawSqlSourceMapper(ms); } } } /** * 获取通用Mapper配置 * * @return */ public Config getConfig() { return config; } /** * 设置通用Mapper配置 * * @param config */ public void setConfig(Config config) { this.config = config; if (config.getResolveClass() != null) { try { EntityHelper.setResolve(config.getResolveClass().newInstance()); } catch (Exception e) { log.error("创建 " + config.getResolveClass().getName() + " 实例失败,请保证该类有默认的构造方法!", e); throw new MapperException("创建 " + config.getResolveClass().getName() + " 实例失败,请保证该类有默认的构造方法!", e); } } if (config.getMappers() != null && config.getMappers().size() > 0) { for (Class mapperClass : config.getMappers()) { registerMapper(mapperClass); } } } /** * 配置属性 * * @param properties */ public void setProperties(Properties properties) { config.setProperties(properties); // 将配置同步到 SqlHelper(控制通过主键进行操作(select, update, delete)时,是否拼接逻辑删除字段的条件) SqlHelper.setLogicDeleteByKey(config.isLogicDeleteByKey()); //注册解析器 if (properties != null) { String resolveClass = properties.getProperty("resolveClass"); if (StringUtil.isNotEmpty(resolveClass)) { try { EntityHelper.setResolve((EntityResolve) Class.forName(resolveClass).newInstance()); } catch (Exception e) { log.error("创建 " + resolveClass + " 实例失败!", e); throw new MapperException("创建 " + resolveClass + " 实例失败!", e); } } } //注册通用接口 if (properties != null) { String mapper = properties.getProperty("mappers"); if (StringUtil.isNotEmpty(mapper)) { String[] mappers = mapper.split(","); for (String mapperClass : mappers) { if (mapperClass.length() > 0) { registerMapper(mapperClass); } } } } } /** * 重新设置SqlSource *

* 执行该方法前必须使用isMapperMethod判断,否则msIdCache会空 * * @param ms * @param mapperTemplate */ public void setSqlSource(MappedStatement ms, MapperTemplate mapperTemplate) { try { if (mapperTemplate != null) { mapperTemplate.setSqlSource(ms); } } catch (Exception e) { throw new MapperException(e); } } /** * 设置原生Mybatis查询的实体映射, *

* JPA的注解优先级将高于mybatis自动映射 */ public void setRawSqlSourceMapper(MappedStatement ms) { ResultMap rm = ms.getResultMaps().get(0); //不处理已经配置映射的查询 if (rm.getResultMappings().isEmpty()) { EntityTable entityTable = EntityHelper.getEntityTableOrNull(rm.getType()); if (entityTable != null) { List resultMaps = new ArrayList<>(); ResultMap resultMap = entityTable.getResultMap(ms.getConfiguration()); if (resultMap != null) { resultMaps.add(resultMap); MetaObject metaObject = MetaObjectUtil.forObject(ms); metaObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps)); } } } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/MapperTemplate.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.SqlSource; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.scripting.xmltags.DynamicSqlSource; import org.apache.ibatis.scripting.xmltags.SqlNode; import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.util.MetaObjectUtil; import tk.mybatis.mapper.util.StringUtil; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import static tk.mybatis.mapper.util.MsUtil.getMapperClass; import static tk.mybatis.mapper.util.MsUtil.getMethodName; /** * 通用Mapper模板类,扩展通用Mapper时需要继承该类 * * @author liuzh */ public abstract class MapperTemplate { private static final XMLLanguageDriver languageDriver = new XMLLanguageDriver(); protected Map methodMap = new ConcurrentHashMap(); protected Map> entityClassMap = new ConcurrentHashMap>(); protected Class mapperClass; protected MapperHelper mapperHelper; public MapperTemplate(Class mapperClass, MapperHelper mapperHelper) { this.mapperClass = mapperClass; this.mapperHelper = mapperHelper; } /** * 该方法仅仅用来初始化ProviderSqlSource * * @param record * @return */ public String dynamicSQL(Object record) { return "dynamicSQL"; } /** * 添加映射方法 * * @param methodName * @param method */ public void addMethodMap(String methodName, Method method) { methodMap.put(methodName, method); } /** * 获取IDENTITY值的表达式 * * @param column * @return */ public String getIDENTITY(EntityColumn column) { return MessageFormat.format(mapperHelper.getConfig().getIDENTITY(), column.getColumn(), column.getProperty(), column.getTable().getName()); } /** * 是否支持该通用方法 * * @param msId * @return */ public boolean supportMethod(String msId) { Class mapperClass = getMapperClass(msId); if (mapperClass != null && this.mapperClass.isAssignableFrom(mapperClass)) { String methodName = getMethodName(msId); return methodMap.get(methodName) != null; } return false; } /** * 设置返回值类型 - 为了让typeHandler在select时有效,改为设置resultMap * * @param ms * @param entityClass */ protected void setResultType(MappedStatement ms, Class entityClass) { EntityTable entityTable = EntityHelper.getEntityTable(entityClass); List resultMaps = new ArrayList(); resultMaps.add(entityTable.getResultMap(ms.getConfiguration())); MetaObject metaObject = MetaObjectUtil.forObject(ms); metaObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps)); } /** * 重新设置SqlSource * * @param ms * @param sqlSource */ protected void setSqlSource(MappedStatement ms, SqlSource sqlSource) { MetaObject msObject = MetaObjectUtil.forObject(ms); msObject.setValue("sqlSource", sqlSource); } /** * 通过xmlSql创建sqlSource * * @param ms * @param xmlSql * @return */ public SqlSource createSqlSource(MappedStatement ms, String xmlSql) { return languageDriver.createSqlSource(ms.getConfiguration(), "", null); } /** * 获取返回值类型 - 实体类型 * * @param ms * @return */ public Class getEntityClass(MappedStatement ms) { String msId = ms.getId(); if (entityClassMap.containsKey(msId)) { return entityClassMap.get(msId); } else { Class mapperClass = getMapperClass(msId); Type[] types = mapperClass.getGenericInterfaces(); for (Type type : types) { if (type instanceof ParameterizedType) { ParameterizedType t = (ParameterizedType) type; if (t.getRawType() == this.mapperClass || this.mapperClass.isAssignableFrom((Class) t.getRawType())) { Type actualType = t.getActualTypeArguments()[0]; Class returnType; if (actualType instanceof Class) { returnType = (Class) actualType; } else if (actualType instanceof ParameterizedType) { // 获取泛型信息后发现任然是泛型的场景 returnType = (Class) ((ParameterizedType)actualType).getRawType(); } else { // GenericArrayType、TypeVariable以及WildcardType不受支持 throw new MapperException(msId + " 方法的泛型信息不受支持!"); } //获取该类型后,第一次对该类型进行初始化 EntityHelper.initEntityNameMap(returnType, mapperHelper.getConfig()); entityClassMap.put(msId, returnType); return returnType; } } } } throw new MapperException("无法获取 " + msId + " 方法的泛型信息!"); } /** * 获取实体类的表名 * * @param entityClass * @return */ protected String tableName(Class entityClass) { EntityTable entityTable = EntityHelper.getEntityTable(entityClass); String prefix = entityTable.getPrefix(); if (StringUtil.isEmpty(prefix)) { //使用全局配置 prefix = mapperHelper.getConfig().getPrefix(); } if (StringUtil.isNotEmpty(prefix)) { return prefix + "." + entityTable.getName(); } return entityTable.getName(); } public Config getConfig() { return mapperHelper.getConfig(); } public String getIDENTITY() { return getConfig().getIDENTITY(); } public boolean isBEFORE() { return getConfig().isBEFORE(); } public boolean isCheckExampleEntityClass() { return getConfig().isCheckExampleEntityClass(); } public boolean isNotEmpty() { return getConfig().isNotEmpty(); } /** * 重新设置SqlSource * * @param ms * @throws java.lang.reflect.InvocationTargetException * @throws IllegalAccessException */ public void setSqlSource(MappedStatement ms) throws Exception { if (this.mapperClass == getMapperClass(ms.getId())) { throw new MapperException("请不要配置或扫描通用Mapper接口类:" + this.mapperClass); } Method method = methodMap.get(getMethodName(ms)); try { //第一种,直接操作ms,不需要返回值 if (method.getReturnType() == Void.TYPE) { method.invoke(this, ms); } //第二种,返回SqlNode else if (SqlNode.class.isAssignableFrom(method.getReturnType())) { SqlNode sqlNode = (SqlNode) method.invoke(this, ms); DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode); setSqlSource(ms, dynamicSqlSource); } //第三种,返回xml形式的sql字符串 else if (String.class.equals(method.getReturnType())) { String xmlSql = (String) method.invoke(this, ms); SqlSource sqlSource = createSqlSource(ms, xmlSql); //替换原有的SqlSource setSqlSource(ms, sqlSource); } else { throw new MapperException("自定义Mapper方法返回类型错误,可选的返回类型为void,SqlNode,String三种!"); } } catch (IllegalAccessException e) { throw new MapperException(e); } catch (InvocationTargetException e) { throw new MapperException(e.getTargetException() != null ? e.getTargetException() : e); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/SelectKeyGenerator.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.executor.ExecutorException; import org.apache.ibatis.executor.keygen.KeyGenerator; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.RowBounds; import java.sql.Statement; import java.util.List; /** * @author Clinton Begin * @author Jeff Butler */ public class SelectKeyGenerator implements KeyGenerator { public static final String SELECT_KEY_SUFFIX = "!selectKey"; private boolean executeBefore; private MappedStatement keyStatement; public SelectKeyGenerator(MappedStatement keyStatement, boolean executeBefore) { this.executeBefore = executeBefore; this.keyStatement = keyStatement; } @Override public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { if (executeBefore) { processGeneratedKeys(executor, ms, parameter); } } @Override public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { if (!executeBefore) { processGeneratedKeys(executor, ms, parameter); } } private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) { try { if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) { String[] keyProperties = keyStatement.getKeyProperties(); final Configuration configuration = ms.getConfiguration(); final MetaObject metaParam = configuration.newMetaObject(parameter); if (keyProperties != null) { // Do not close keyExecutor. // The transaction will be closed by parent executor. Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE); List values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); if (values.size() == 0) { throw new ExecutorException("SelectKey returned no data."); } else if (values.size() > 1) { throw new ExecutorException("SelectKey returned more than one value."); } else { MetaObject metaResult = configuration.newMetaObject(values.get(0)); if (keyProperties.length == 1) { if (metaResult.hasGetter(keyProperties[0])) { setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0])); } else { // no getter for the property - maybe just a single value object // so try that setValue(metaParam, keyProperties[0], values.get(0)); } } else { handleMultipleProperties(keyProperties, metaParam, metaResult); } } } } } catch (ExecutorException e) { throw e; } catch (Exception e) { throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e); } } private void handleMultipleProperties(String[] keyProperties, MetaObject metaParam, MetaObject metaResult) { String[] keyColumns = keyStatement.getKeyColumns(); if (keyColumns == null || keyColumns.length == 0) { // no key columns specified, just use the property names for (String keyProperty : keyProperties) { setValue(metaParam, keyProperty, metaResult.getValue(keyProperty)); } } else { if (keyColumns.length != keyProperties.length) { throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties."); } for (int i = 0; i < keyProperties.length; i++) { setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i])); } } } private void setValue(MetaObject metaParam, String property, Object value) { if (metaParam.hasSetter(property)) { if (metaParam.hasGetter(property)) { Object defaultValue = metaParam.getValue(property); if (defaultValue != null) { return; } } metaParam.setValue(property, value); } else { throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + "."); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/SelectKeyHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; import org.apache.ibatis.executor.keygen.KeyGenerator; import org.apache.ibatis.executor.keygen.NoKeyGenerator; import org.apache.ibatis.mapping.*; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.scripting.defaults.RawSqlSource; import org.apache.ibatis.session.Configuration; import tk.mybatis.mapper.code.ORDER; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.util.MetaObjectUtil; import java.util.ArrayList; import java.util.List; /** * 创建 selectKey * * @author liuzh * @since 2017/7/9. */ public class SelectKeyHelper { /** * 新建SelectKey节点 * * @param ms * @param column */ public static void newSelectKeyMappedStatement(MappedStatement ms, EntityColumn column, Class entityClass, Boolean executeBefore, String identity) { String keyId = ms.getId() + SelectKeyGenerator.SELECT_KEY_SUFFIX; if (ms.getConfiguration().hasKeyGenerator(keyId)) { return; } //defaults Configuration configuration = ms.getConfiguration(); KeyGenerator keyGenerator; String IDENTITY = (column.getGenerator() == null || "".equals(column.getGenerator())) ? identity : column.getGenerator(); if ("JDBC".equalsIgnoreCase(IDENTITY)) { keyGenerator = new Jdbc3KeyGenerator(); } else { SqlSource sqlSource = new RawSqlSource(configuration, IDENTITY, entityClass); MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, keyId, sqlSource, SqlCommandType.SELECT); statementBuilder.resource(ms.getResource()); statementBuilder.fetchSize(null); statementBuilder.statementType(StatementType.STATEMENT); statementBuilder.keyGenerator(new NoKeyGenerator()); statementBuilder.keyProperty(column.getProperty()); statementBuilder.keyColumn(null); statementBuilder.databaseId(null); statementBuilder.lang(configuration.getDefaultScriptingLanuageInstance()); statementBuilder.resultOrdered(false); statementBuilder.resulSets(null); statementBuilder.timeout(configuration.getDefaultStatementTimeout()); List parameterMappings = new ArrayList(); ParameterMap.Builder inlineParameterMapBuilder = new ParameterMap.Builder( configuration, statementBuilder.id() + "-Inline", entityClass, parameterMappings); statementBuilder.parameterMap(inlineParameterMapBuilder.build()); List resultMaps = new ArrayList(); ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder( configuration, statementBuilder.id() + "-Inline", column.getJavaType(), new ArrayList(), null); resultMaps.add(inlineResultMapBuilder.build()); statementBuilder.resultMaps(resultMaps); statementBuilder.resultSetType(null); statementBuilder.flushCacheRequired(false); statementBuilder.useCache(false); statementBuilder.cache(null); MappedStatement statement = statementBuilder.build(); try { configuration.addMappedStatement(statement); } catch (Exception e) { //ignore } MappedStatement keyStatement = configuration.getMappedStatement(keyId, false); //如果单独设置了 order,使用 column 提供的,否则使用全局的 keyGenerator = new SelectKeyGenerator(keyStatement, column.getOrder() != ORDER.DEFAULT ? (column.getOrder() == ORDER.BEFORE) : executeBefore); try { configuration.addKeyGenerator(keyId, keyGenerator); } catch (Exception e) { //ignore } } //keyGenerator try { MetaObject msObject = MetaObjectUtil.forObject(ms); msObject.setValue("keyGenerator", keyGenerator); msObject.setValue("keyProperties", column.getTable().getKeyProperties()); msObject.setValue("keyColumns", column.getTable().getKeyColumns()); } catch (Exception e) { //ignore } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/SqlHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.mapperhelper; import tk.mybatis.mapper.LogicDeleteException; import tk.mybatis.mapper.annotation.LogicDelete; import tk.mybatis.mapper.annotation.Version; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.IDynamicTableName; import tk.mybatis.mapper.util.StringUtil; import tk.mybatis.mapper.version.VersionException; import java.util.Set; /** * 拼常用SQL的工具类 * * @author liuzh * @since 2015-11-03 22:40 */ public class SqlHelper { /** * 控制通过主键进行操作(select, update, delete)时,是否拼接逻辑删除字段的条件(默认 true,保持兼容) */ private static boolean logicDeleteByKey = true; public static boolean isLogicDeleteByKey() { return logicDeleteByKey; } public static void setLogicDeleteByKey(boolean logicDeleteByKey) { SqlHelper.logicDeleteByKey = logicDeleteByKey; } /** * 获取表名 - 支持动态表名 * * @param entityClass * @param tableName * @return */ public static String getDynamicTableName(Class entityClass, String tableName) { if (IDynamicTableName.class.isAssignableFrom(entityClass)) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(""); sql.append("${dynamicTableName}\n"); sql.append(""); //不支持指定列的时候查询全部列 sql.append(""); sql.append(tableName); sql.append(""); sql.append(""); return sql.toString(); } else { return tableName; } } /** * 获取表名 - 支持动态表名,该方法用于多个入参时,通过parameterName指定入参中实体类的@Param的注解值 * * @param entityClass * @param tableName * @param parameterName * @return */ public static String getDynamicTableName(Class entityClass, String tableName, String parameterName) { if (IDynamicTableName.class.isAssignableFrom(entityClass)) { if (StringUtil.isNotEmpty(parameterName)) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(""); sql.append("${" + parameterName + ".dynamicTableName}"); sql.append(""); //不支持指定列的时候查询全部列 sql.append(""); sql.append(tableName); sql.append(""); sql.append(""); return sql.toString(); } else { return getDynamicTableName(entityClass, tableName); } } else { return tableName; } } /** * * * @param column * @return */ public static String getBindCache(EntityColumn column) { StringBuilder sql = new StringBuilder(); sql.append(""); return sql.toString(); } /** * * * @param column * @return */ public static String getBindValue(EntityColumn column, String value) { StringBuilder sql = new StringBuilder(); sql.append(""); return sql.toString(); } /** * * * @param column * @return */ public static String getIfCacheNotNull(EntityColumn column, String contents) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(contents); sql.append(""); return sql.toString(); } /** * 如果_cache == null * * @param column * @return */ public static String getIfCacheIsNull(EntityColumn column, String contents) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(contents); sql.append(""); return sql.toString(); } /** * 判断自动!=null的条件结构 * * @param column * @param contents * @param empty * @return */ public static String getIfNotNull(EntityColumn column, String contents, boolean empty) { return getIfNotNull(null, column, contents, empty); } /** * 判断自动==null的条件结构 * * @param column * @param contents * @param empty * @return */ public static String getIfIsNull(EntityColumn column, String contents, boolean empty) { return getIfIsNull(null, column, contents, empty); } /** * 判断自动!=null的条件结构 * * @param entityName * @param column * @param contents * @param empty * @return */ public static String getIfNotNull(String entityName, EntityColumn column, String contents, boolean empty) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(contents); sql.append(""); return sql.toString(); } /** * 判断自动==null的条件结构 * * @param entityName * @param column * @param contents * @param empty * @return */ public static String getIfIsNull(String entityName, EntityColumn column, String contents, boolean empty) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(contents); sql.append(""); return sql.toString(); } /** * 获取所有查询列,如id,name,code... * * @param entityClass * @return */ public static String getAllColumns(Class entityClass) { Set columnSet = EntityHelper.getColumns(entityClass); StringBuilder sql = new StringBuilder(); for (EntityColumn entityColumn : columnSet) { sql.append(entityColumn.getColumn()).append(","); } return sql.substring(0, sql.length() - 1); } /** * select xxx,xxx... * * @param entityClass * @return */ public static String selectAllColumns(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append("SELECT "); sql.append(getAllColumns(entityClass)); sql.append(" "); return sql.toString(); } /** * select count(x) * * @param entityClass * @return */ public static String selectCount(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append("SELECT "); Set pkColumns = EntityHelper.getPKColumns(entityClass); if (pkColumns.size() == 1) { sql.append("COUNT(").append(pkColumns.iterator().next().getColumn()).append(") "); } else { sql.append("COUNT(*) "); } return sql.toString(); } /** * select case when count(x) > 0 then 1 else 0 end * * @param entityClass * @return */ public static String selectCountExists(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append("SELECT CASE WHEN "); Set pkColumns = EntityHelper.getPKColumns(entityClass); if (pkColumns.size() == 1) { sql.append("COUNT(").append(pkColumns.iterator().next().getColumn()).append(") "); } else { sql.append("COUNT(*) "); } sql.append(" > 0 THEN 1 ELSE 0 END AS result "); return sql.toString(); } /** * from tableName - 动态表名 * * @param entityClass * @param defaultTableName * @return */ public static String fromTable(Class entityClass, String defaultTableName) { StringBuilder sql = new StringBuilder(); sql.append(" FROM "); sql.append(getDynamicTableName(entityClass, defaultTableName)); sql.append(" "); return sql.toString(); } /** * update tableName - 动态表名 * * @param entityClass * @param defaultTableName * @return */ public static String updateTable(Class entityClass, String defaultTableName) { return updateTable(entityClass, defaultTableName, null); } /** * update tableName - 动态表名 * * @param entityClass * @param defaultTableName 默认表名 * @param entityName 别名 * @return */ public static String updateTable(Class entityClass, String defaultTableName, String entityName) { StringBuilder sql = new StringBuilder(); sql.append("UPDATE "); sql.append(getDynamicTableName(entityClass, defaultTableName, entityName)); sql.append(" "); return sql.toString(); } /** * delete tableName - 动态表名 * * @param entityClass * @param defaultTableName * @return */ public static String deleteFromTable(Class entityClass, String defaultTableName) { StringBuilder sql = new StringBuilder(); sql.append("DELETE FROM "); sql.append(getDynamicTableName(entityClass, defaultTableName)); sql.append(" "); return sql.toString(); } /** * insert into tableName - 动态表名 * * @param entityClass * @param defaultTableName * @return */ public static String insertIntoTable(Class entityClass, String defaultTableName) { StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(getDynamicTableName(entityClass, defaultTableName)); sql.append(" "); return sql.toString(); } /** * insert into tableName - 动态表名 * * @param entityClass * @param defaultTableName * @param parameterName 动态表名的参数名 * @return */ public static String insertIntoTable(Class entityClass, String defaultTableName, String parameterName) { StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(getDynamicTableName(entityClass, defaultTableName, parameterName)); sql.append(" "); return sql.toString(); } /** * insert table()列 * * @param entityClass * @param skipId 是否从列中忽略id类型 * @param notNull 是否判断!=null * @param notEmpty 是否判断String类型!='' * @return */ public static String insertColumns(Class entityClass, boolean skipId, boolean notNull, boolean notEmpty) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (!column.isInsertable()) { continue; } if (skipId && column.isId()) { continue; } if (notNull) { sql.append(SqlHelper.getIfNotNull(column, column.getColumn() + ",", notEmpty)); } else { sql.append(column.getColumn() + ","); } } sql.append(""); return sql.toString(); } /** * insert-values()列 * * @param entityClass * @param skipId 是否从列中忽略id类型 * @param notNull 是否判断!=null * @param notEmpty 是否判断String类型!='' * @return */ public static String insertValuesColumns(Class entityClass, boolean skipId, boolean notNull, boolean notEmpty) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (!column.isInsertable()) { continue; } if (skipId && column.isId()) { continue; } if (notNull) { sql.append(SqlHelper.getIfNotNull(column, column.getColumnHolder() + ",", notEmpty)); } else { sql.append(column.getColumnHolder() + ","); } } sql.append(""); return sql.toString(); } /** * update set列 * * @param entityClass 实体Class * @param entityName 实体映射名 * @param notNull 是否判断!=null * @param notEmpty 是否判断String类型!='' * @return XML中的SET语句块 */ public static String updateSetColumns(Class entityClass, String entityName, boolean notNull, boolean notEmpty) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); //对乐观锁的支持 EntityColumn versionColumn = null; // 逻辑删除列 EntityColumn logicDeleteColumn = null; //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(Version.class)) { if (versionColumn != null) { throw new VersionException(entityClass.getName() + " 中包含多个带有 @Version 注解的字段,一个类中只能存在一个带有 @Version 注解的字段!"); } versionColumn = column; } if (column.getEntityField().isAnnotationPresent(LogicDelete.class)) { if (logicDeleteColumn != null) { throw new LogicDeleteException(entityClass.getName() + " 中包含多个带有 @LogicDelete 注解的字段,一个类中只能存在一个带有 @LogicDelete 注解的字段!"); } logicDeleteColumn = column; } if (!column.isId() && column.isUpdatable()) { if (column == versionColumn) { Version version = versionColumn.getEntityField().getAnnotation(Version.class); String versionClass = version.nextVersion().getName(); sql.append(""); sql.append(column.getColumn()).append(" = #{").append(column.getProperty()).append("Version},"); } else if (column == logicDeleteColumn) { sql.append(logicDeleteColumnEqualsValue(column, false)).append(","); } else if (notNull) { sql.append(SqlHelper.getIfNotNull(entityName, column, column.getColumnEqualsHolder(entityName) + ",", notEmpty)); } else { sql.append(column.getColumnEqualsHolder(entityName) + ","); } } } sql.append(""); return sql.toString(); } /** * update set列,不考虑乐观锁注解 @Version * * @param entityClass * @param entityName 实体映射名 * @param notNull 是否判断!=null * @param notEmpty 是否判断String类型!='' * @return */ public static String updateSetColumnsIgnoreVersion(Class entityClass, String entityName, boolean notNull, boolean notEmpty) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); // 逻辑删除列 EntityColumn logicDeleteColumn = null; //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(LogicDelete.class)) { if (logicDeleteColumn != null) { throw new LogicDeleteException(entityClass.getName() + " 中包含多个带有 @LogicDelete 注解的字段,一个类中只能存在一个带有 @LogicDelete 注解的字段!"); } logicDeleteColumn = column; } if (!column.isId() && column.isUpdatable()) { if (column.getEntityField().isAnnotationPresent(Version.class)) { //ignore } else if (column == logicDeleteColumn) { sql.append(logicDeleteColumnEqualsValue(column, false)).append(","); } else if (notNull) { sql.append(SqlHelper.getIfNotNull(entityName, column, column.getColumnEqualsHolder(entityName) + ",", notEmpty)); } else { sql.append(column.getColumnEqualsHolder(entityName)).append(","); } } else if (column.isId() && column.isUpdatable()) { //set id = id, sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(","); } } sql.append(""); return sql.toString(); } /** * 不是所有参数都是 null 的检查 * * @param parameterName 参数名 * @param columnSet 需要检查的列 * @return */ public static String notAllNullParameterCheck(String parameterName, Set columnSet) { StringBuilder sql = new StringBuilder(); sql.append(" 0) { fields.append(","); } fields.append(column.getProperty()); } sql.append(fields); sql.append("')\"/>"); return sql.toString(); } /** * Example 中包含至少 1 个查询条件 * * @param parameterName 参数名 * @return */ public static String exampleHasAtLeastOneCriteriaCheck(String parameterName) { StringBuilder sql = new StringBuilder(); sql.append(""); return sql.toString(); } /** * where主键条件 * * @param entityClass * @return */ public static String wherePKColumns(Class entityClass) { return wherePKColumns(entityClass, false); } /** * where主键条件 * * @param entityClass * @param useVersion * @return */ public static String wherePKColumns(Class entityClass, boolean useVersion) { return wherePKColumns(entityClass, null, useVersion); } /** * where主键条件 * * @param entityClass * @param entityName * @param useVersion * @return */ public static String wherePKColumns(Class entityClass, String entityName, boolean useVersion) { StringBuilder sql = new StringBuilder(); boolean hasLogicDelete = hasLogicDeleteColumn(entityClass); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getPKColumns(entityClass); //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { sql.append(" AND ").append(column.getColumnEqualsHolder(entityName)); } if (useVersion) { sql.append(whereVersion(entityClass)); } if (hasLogicDelete && isLogicDeleteByKey()) { sql.append(whereLogicDelete(entityClass, false)); } sql.append(""); return sql.toString(); } /** * where所有列的条件,会判断是否!=null * * @param entityClass * @param empty * @return */ public static String whereAllIfColumns(Class entityClass, boolean empty) { return whereAllIfColumns(entityClass, empty, false); } /** * where所有列的条件,会判断是否!=null * * @param entityClass * @param empty * @param useVersion * @return */ public static String whereAllIfColumns(Class entityClass, boolean empty, boolean useVersion) { StringBuilder sql = new StringBuilder(); boolean hasLogicDelete = false; sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (!useVersion || !column.getEntityField().isAnnotationPresent(Version.class)) { // 逻辑删除,后面拼接逻辑删除字段的未删除条件 if (logicDeleteColumn != null && logicDeleteColumn == column) { hasLogicDelete = true; continue; } sql.append(getIfNotNull(column, " AND " + column.getColumnEqualsHolder(), empty)); } } if (useVersion) { sql.append(whereVersion(entityClass)); } if (hasLogicDelete) { sql.append(whereLogicDelete(entityClass, false)); } sql.append(""); return sql.toString(); } /** * 乐观锁字段条件 * * @param entityClass * @return */ public static String whereVersion(Class entityClass){ return whereVersion(entityClass,null); } /** * 乐观锁字段条件 * * @param entityClass * @param entityName 实体名称 * @return */ public static String whereVersion(Class entityClass,String entityName) { Set columnSet = EntityHelper.getColumns(entityClass); boolean hasVersion = false; String result = ""; for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(Version.class)) { if (hasVersion) { throw new VersionException(entityClass.getName() + " 中包含多个带有 @Version 注解的字段,一个类中只能存在一个带有 @Version 注解的字段!"); } hasVersion = true; result = " AND " + column.getColumnEqualsHolder(entityName); } } return result; } /** * 逻辑删除的where条件,没有逻辑删除注解则返回空字符串 *
* AND column = value * * @param entityClass * @param isDeleted true:已经逻辑删除,false:未逻辑删除 * @return */ public static String whereLogicDelete(Class entityClass, boolean isDeleted) { String value = logicDeleteColumnEqualsValue(entityClass, isDeleted); return "".equals(value) ? "" : " AND " + value; } /** * 返回格式: column = value *
* 默认isDeletedValue = 1 notDeletedValue = 0 *
* 则返回is_deleted = 1 或 is_deleted = 0 *
* 若没有逻辑删除注解,则返回空字符串 * * @param entityClass * @param isDeleted true 已经逻辑删除 false 未逻辑删除 */ public static String logicDeleteColumnEqualsValue(Class entityClass, boolean isDeleted) { EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); if (logicDeleteColumn != null) { return logicDeleteColumnEqualsValue(logicDeleteColumn, isDeleted); } return ""; } /** * 返回格式: column = value *
* 默认isDeletedValue = 1 notDeletedValue = 0 *
* 则返回is_deleted = 1 或 is_deleted = 0 *
* 若没有逻辑删除注解,则返回空字符串 * * @param column * @param isDeleted true 已经逻辑删除 false 未逻辑删除 */ public static String logicDeleteColumnEqualsValue(EntityColumn column, boolean isDeleted) { String result = ""; if (column.getEntityField().isAnnotationPresent(LogicDelete.class)) { Integer logicDeletedValue = getLogicDeletedValue(column, isDeleted); if(logicDeletedValue==null){ result = column.getColumn() + " is null "; }else { result = column.getColumn() + " = " + logicDeletedValue; } } return result; } /** * 获取逻辑删除注解的参数值 * * @param column * @param isDeleted true:逻辑删除的值,false:未逻辑删除的值 * @return */ public static Integer getLogicDeletedValue(EntityColumn column, boolean isDeleted) { if (!column.getEntityField().isAnnotationPresent(LogicDelete.class)) { throw new LogicDeleteException(column.getColumn() + " 没有 @LogicDelete 注解!"); } LogicDelete logicDelete = column.getEntityField().getAnnotation(LogicDelete.class); if (isDeleted) { return logicDelete.isNullForDeletedValue()?null: logicDelete.isDeletedValue(); } return logicDelete.isNullForNotDeletedValue()?null: logicDelete.notDeletedValue(); } /** * 是否有逻辑删除的注解 * * @param entityClass * @return */ public static boolean hasLogicDeleteColumn(Class entityClass) { return getLogicDeleteColumn(entityClass) != null; } /** * 获取逻辑删除注解的列,若没有返回null * * @param entityClass * @return */ public static EntityColumn getLogicDeleteColumn(Class entityClass) { EntityColumn logicDeleteColumn = null; Set columnSet = EntityHelper.getColumns(entityClass); boolean hasLogicDelete = false; for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(LogicDelete.class)) { if (hasLogicDelete) { throw new LogicDeleteException(entityClass.getName() + " 中包含多个带有 @LogicDelete 注解的字段,一个类中只能存在一个带有 @LogicDelete 注解的字段!"); } hasLogicDelete = true; logicDeleteColumn = column; } } return logicDeleteColumn; } /** * 获取默认的orderBy,通过注解设置的 * * @param entityClass * @return */ public static String orderByDefault(Class entityClass) { StringBuilder sql = new StringBuilder(); String orderByClause = EntityHelper.getOrderByClause(entityClass); if (orderByClause.length() > 0) { sql.append(" ORDER BY "); sql.append(orderByClause); } return sql.toString(); } /** * example支持查询指定列时 * * @return */ public static String exampleSelectColumns(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(""); sql.append(""); sql.append("${selectColumn}"); sql.append(""); sql.append(""); //不支持指定列的时候查询全部列 sql.append(""); sql.append(getAllColumns(entityClass)); sql.append(""); sql.append(""); return sql.toString(); } /** * example支持查询指定列时 * * @return */ public static String exampleCountColumn(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(""); sql.append("COUNT(distinct ${countColumn})"); sql.append(""); sql.append(""); sql.append("COUNT(*)"); sql.append(""); sql.append(""); return sql.toString(); } /** * example查询中的orderBy条件,会判断默认orderBy * * @return */ public static String exampleOrderBy(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append("order by ${orderByClause}"); sql.append(""); String orderByClause = EntityHelper.getOrderByClause(entityClass); if (orderByClause.length() > 0) { sql.append(""); sql.append("ORDER BY " + orderByClause); sql.append(""); } return sql.toString(); } /** * example查询中的orderBy条件,会判断默认orderBy * * @return */ public static String exampleOrderBy(String entityName, Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append("order by ${").append(entityName).append(".orderByClause}"); sql.append(""); String orderByClause = EntityHelper.getOrderByClause(entityClass); if (orderByClause.length() > 0) { sql.append(""); sql.append("ORDER BY " + orderByClause); sql.append(""); } return sql.toString(); } /** * example 支持 for update * * @return */ public static String exampleForUpdate() { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append("FOR UPDATE"); sql.append(""); return sql.toString(); } /** * example 支持 for update * * @return */ public static String exampleCheck(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append(""); return sql.toString(); } /** * Example查询中的where结构,用于只有一个Example参数时 * * @return */ public static String exampleWhereClause() { return "" + "\n" + " ${@tk.mybatis.mapper.util.OGNL@andNotLogicDelete(_parameter)}" + " \n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criteria)}" + " \n" + " \n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition}\n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value}\n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value} and #{criterion.secondValue}\n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition}\n" + " \n" + " #{listItem}\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "" + ""; } /** * Example-Update中的where结构,用于多个参数时,Example带@Param("example")注解时 * * @return */ public static String updateByExampleWhereClause() { return "\n" + " ${@tk.mybatis.mapper.util.OGNL@andNotLogicDelete(example)}" + " \n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criteria)}" + " \n" + " \n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition}\n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value}\n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value} and #{criterion.secondValue}\n" + " \n" + " \n" + " ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition}\n" + " \n" + " #{listItem}\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/resolve/DefaultEntityResolve.java ================================================ package tk.mybatis.mapper.mapperhelper.resolve; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.UnknownTypeHandler; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.annotation.ColumnType; import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.annotation.NameStyle; import tk.mybatis.mapper.annotation.Order; import tk.mybatis.mapper.code.IdentityDialect; import tk.mybatis.mapper.code.ORDER; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityField; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.genid.GenId; import tk.mybatis.mapper.gensql.GenSql; import tk.mybatis.mapper.mapperhelper.FieldHelper; import tk.mybatis.mapper.util.SimpleTypeUtil; import tk.mybatis.mapper.util.SqlReservedWords; import tk.mybatis.mapper.util.StringUtil; import jakarta.persistence.*; import java.text.MessageFormat; import java.util.LinkedHashSet; import java.util.List; /** * @author liuzh */ public class DefaultEntityResolve implements EntityResolve { private final Log log = LogFactory.getLog(DefaultEntityResolve.class); @Override public EntityTable resolveEntity(Class entityClass, Config config) { Style style = config.getStyle(); //style,该注解优先于全局配置 if (entityClass.isAnnotationPresent(NameStyle.class)) { NameStyle nameStyle = entityClass.getAnnotation(NameStyle.class); style = nameStyle.value(); } //创建并缓存EntityTable EntityTable entityTable = null; if (entityClass.isAnnotationPresent(Table.class)) { Table table = entityClass.getAnnotation(Table.class); if (!"".equals(table.name())) { entityTable = new EntityTable(entityClass); entityTable.setTable(table); } } if (entityTable == null) { entityTable = new EntityTable(entityClass); //可以通过stye控制 String tableName = StringUtil.convertByStyle(entityClass.getSimpleName(), style); //自动处理关键字 if (StringUtil.isNotEmpty(config.getWrapKeyword()) && SqlReservedWords.containsWord(tableName)) { tableName = MessageFormat.format(config.getWrapKeyword(), tableName); } entityTable.setName(tableName); } entityTable.setEntityClassColumns(new LinkedHashSet()); entityTable.setEntityClassPKColumns(new LinkedHashSet()); //处理所有列 List fields = null; if (config.isEnableMethodAnnotation()) { fields = FieldHelper.getAll(entityClass); } else { fields = FieldHelper.getFields(entityClass); } for (EntityField field : fields) { //如果启用了简单类型,就做简单类型校验,如果不是简单类型,直接跳过 //3.5.0 如果启用了枚举作为简单类型,就不会自动忽略枚举类型 //4.0 如果标记了 Column 或 ColumnType 注解,也不忽略 if (!config.isUseSimpleType() //关闭简单类型限制时,所有字段都处理 || (config.isUseSimpleType() && SimpleTypeUtil.isSimpleType(field.getJavaType())) //开启简单类型时只处理包含的简单类型 || field.isAnnotationPresent(Column.class) //有注解的处理,不考虑类型 || field.isAnnotationPresent(ColumnType.class) //有注解的处理,不考虑类型 || (config.isEnumAsSimpleType() && Enum.class.isAssignableFrom(field.getJavaType()))) { //开启枚举作为简单类型时处理 processField(entityTable, field, config, style); } } //当pk.size=0的时候使用所有列作为主键 if (entityTable.getEntityClassPKColumns().size() == 0) { entityTable.setEntityClassPKColumns(entityTable.getEntityClassColumns()); } entityTable.initPropertyMap(); return entityTable; } /** * 处理字段 * * @param entityTable * @param field * @param config * @param style */ protected void processField(EntityTable entityTable, EntityField field, Config config, Style style) { //排除字段 if (field.isAnnotationPresent(Transient.class)) { return; } //Id EntityColumn entityColumn = new EntityColumn(entityTable); //是否使用 {xx, javaType=xxx} entityColumn.setUseJavaType(config.isUseJavaType()); //记录 field 信息,方便后续扩展使用 entityColumn.setEntityField(field); if (field.isAnnotationPresent(Id.class)) { entityColumn.setId(true); } //Column String columnName = null; if (field.isAnnotationPresent(Column.class)) { Column column = field.getAnnotation(Column.class); columnName = column.name(); entityColumn.setUpdatable(column.updatable()); entityColumn.setInsertable(column.insertable()); } //ColumnType if (field.isAnnotationPresent(ColumnType.class)) { ColumnType columnType = field.getAnnotation(ColumnType.class); //是否为 blob 字段 entityColumn.setBlob(columnType.isBlob()); //column可以起到别名的作用 if (StringUtil.isEmpty(columnName) && StringUtil.isNotEmpty(columnType.column())) { columnName = columnType.column(); } if (columnType.jdbcType() != JdbcType.UNDEFINED) { entityColumn.setJdbcType(columnType.jdbcType()); } if (columnType.typeHandler() != UnknownTypeHandler.class) { entityColumn.setTypeHandler(columnType.typeHandler()); } } //列名 if (StringUtil.isEmpty(columnName)) { columnName = StringUtil.convertByStyle(field.getName(), style); } //自动处理关键字 if (StringUtil.isNotEmpty(config.getWrapKeyword()) && SqlReservedWords.containsWord(columnName)) { columnName = MessageFormat.format(config.getWrapKeyword(), columnName); } entityColumn.setProperty(field.getName()); entityColumn.setColumn(columnName); entityColumn.setJavaType(field.getJavaType()); if (field.getJavaType().isPrimitive()) { log.warn("通用 Mapper 警告信息: <[" + entityColumn + "]> 使用了基本类型,基本类型在动态 SQL 中由于存在默认值,因此任何时候都不等于 null,建议修改基本类型为对应的包装类型!"); } //OrderBy processOrderBy(entityTable, field, entityColumn); //处理主键策略 processKeyGenerator(entityTable, field, entityColumn); entityTable.getEntityClassColumns().add(entityColumn); if (entityColumn.isId()) { entityTable.getEntityClassPKColumns().add(entityColumn); } } /** * 处理排序 * * @param entityTable * @param field * @param entityColumn */ protected void processOrderBy(EntityTable entityTable, EntityField field, EntityColumn entityColumn) { String orderBy = ""; if (field.isAnnotationPresent(OrderBy.class)) { orderBy = field.getAnnotation(OrderBy.class).value(); if ("".equals(orderBy)) { orderBy = "ASC"; } log.warn(OrderBy.class + " is outdated, use " + Order.class + " instead!"); } if (field.isAnnotationPresent(Order.class)) { Order order = field.getAnnotation(Order.class); if ("".equals(order.value()) && "".equals(orderBy)) { orderBy = "ASC"; } else { orderBy = order.value(); } entityColumn.setOrderPriority(order.priority()); } if (StringUtil.isNotEmpty(orderBy)) { entityColumn.setOrderBy(orderBy); } } /** * 处理主键策略 * * @param entityTable * @param field * @param entityColumn */ protected void processKeyGenerator(EntityTable entityTable, EntityField field, EntityColumn entityColumn) { //KeySql 优先级最高 if (field.isAnnotationPresent(KeySql.class)) { processKeySql(entityTable, entityColumn, field.getAnnotation(KeySql.class)); } else if (field.isAnnotationPresent(GeneratedValue.class)) { //执行 sql - selectKey processGeneratedValue(entityTable, entityColumn, field.getAnnotation(GeneratedValue.class)); } } /** * 处理 GeneratedValue 注解 * * @param entityTable * @param entityColumn * @param generatedValue */ protected void processGeneratedValue(EntityTable entityTable, EntityColumn entityColumn, GeneratedValue generatedValue) { if ("JDBC".equals(generatedValue.generator())) { entityColumn.setIdentity(true); entityColumn.setGenerator("JDBC"); entityTable.setKeyProperties(entityColumn.getProperty()); entityTable.setKeyColumns(entityColumn.getColumn()); } else { //允许通过generator来设置获取id的sql,例如mysql=CALL IDENTITY(),hsqldb=SELECT SCOPE_IDENTITY() //允许通过拦截器参数设置公共的generator if (generatedValue.strategy() == GenerationType.IDENTITY) { //mysql的自动增长 entityColumn.setIdentity(true); if (!"".equals(generatedValue.generator())) { String generator = null; IdentityDialect identityDialect = IdentityDialect.getDatabaseDialect(generatedValue.generator()); if (identityDialect != null) { generator = identityDialect.getIdentityRetrievalStatement(); } else { generator = generatedValue.generator(); } entityColumn.setGenerator(generator); } } else { throw new MapperException(entityColumn.getProperty() + " - 该字段@GeneratedValue配置只允许以下几种形式:" + "\n1.useGeneratedKeys的@GeneratedValue(generator=\\\"JDBC\\\") " + "\n2.类似mysql数据库的@GeneratedValue(strategy=GenerationType.IDENTITY[,generator=\"Mysql\"])"); } } } /** * 处理 KeySql 注解 * * @param entityTable * @param entityColumn * @param keySql */ protected void processKeySql(EntityTable entityTable, EntityColumn entityColumn, KeySql keySql) { if (keySql.useGeneratedKeys()) { entityColumn.setIdentity(true); entityColumn.setGenerator("JDBC"); entityTable.setKeyProperties(entityColumn.getProperty()); entityTable.setKeyColumns(entityColumn.getColumn()); } else if (keySql.dialect() == IdentityDialect.DEFAULT) { entityColumn.setIdentity(true); entityColumn.setOrder(ORDER.AFTER); } else if (keySql.dialect() != IdentityDialect.NULL) { //自动增长 entityColumn.setIdentity(true); entityColumn.setOrder(ORDER.AFTER); entityColumn.setGenerator(keySql.dialect().getIdentityRetrievalStatement()); } else if (StringUtil.isNotEmpty(keySql.sql())) { entityColumn.setIdentity(true); entityColumn.setOrder(keySql.order()); entityColumn.setGenerator(keySql.sql()); } else if (keySql.genSql() != GenSql.NULL.class) { entityColumn.setIdentity(true); entityColumn.setOrder(keySql.order()); try { GenSql genSql = keySql.genSql().newInstance(); entityColumn.setGenerator(genSql.genSql(entityTable, entityColumn)); } catch (Exception e) { log.error("实例化 GenSql 失败: " + e, e); throw new MapperException("实例化 GenSql 失败: " + e, e); } } else if (keySql.genId() != GenId.NULL.class) { entityColumn.setIdentity(false); entityColumn.setGenIdClass(keySql.genId()); } else { throw new MapperException(entityTable.getEntityClass().getName() + " 类中的 @KeySql 注解配置无效!"); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/mapperhelper/resolve/EntityResolve.java ================================================ package tk.mybatis.mapper.mapperhelper.resolve; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityTable; /** * 解析实体类接口 * * @author liuzh */ public interface EntityResolve { /** * 解析类为 EntityTable * * @param entityClass * @param config * @return */ EntityTable resolveEntity(Class entityClass, Config config); } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/provider/EmptyProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.provider; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; /** * 空方法Mapper接口默认MapperTemplate *

* 如BaseSelectMapper,接口纯继承,不包含任何方法 */ public class EmptyProvider extends MapperTemplate { public EmptyProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } @Override public boolean supportMethod(String msId) { return false; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/session/Configuration.java ================================================ package tk.mybatis.mapper.session; import org.apache.ibatis.mapping.MappedStatement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.util.Properties; /** * 使用提供的 Configuration 可以在纯 Java 或者 Spring(mybatis-spring-1.3.0+) 模式中使用 * * @author liuzh */ public class Configuration extends org.apache.ibatis.session.Configuration { private final Logger log = LoggerFactory.getLogger(Configuration.class); private MapperHelper mapperHelper; /** * 直接注入 mapperHelper * * @param mapperHelper */ public void setMapperHelper(MapperHelper mapperHelper) { this.mapperHelper = mapperHelper; } /** * 使用属性方式配置 * * @param properties */ public void setMapperProperties(Properties properties) { if (this.mapperHelper == null) { this.mapperHelper = new MapperHelper(); } this.mapperHelper.setProperties(properties); } /** * 使用 Config 配置 * * @param config */ public void setConfig(Config config) { if (mapperHelper == null) { mapperHelper = new MapperHelper(); } mapperHelper.setConfig(config); } @Override public void addMappedStatement(MappedStatement ms) { try { super.addMappedStatement(ms); //没有任何配置时,使用默认配置 if (this.mapperHelper == null) { this.mapperHelper = new MapperHelper(); } this.mapperHelper.processMappedStatement(ms); } catch (IllegalArgumentException e) { //这里的异常是导致 Spring 启动死循环的关键位置,为了避免后续会吞异常,这里直接输出 log.error(e.getMessage(), e); throw new RuntimeException(e); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/Assert.java ================================================ package tk.mybatis.mapper.util; import java.util.Collection; import java.util.Map; /** * @author liuzh */ public abstract class Assert { public static void isTrue(boolean expression, String errorMsg) throws IllegalArgumentException { if (!expression) { throw new IllegalArgumentException(errorMsg); } } public static void isNull(Object object, String errorMsg) throws IllegalArgumentException { if (object != null) { throw new IllegalArgumentException(errorMsg); } } public static T notNull(T object, String errorMsg) throws NullPointerException { if (object == null) { throw new NullPointerException(errorMsg); } return object; } public static String notEmpty(String text, String errorMsg) throws IllegalArgumentException { if (text == null || text.length() == 0) { throw new IllegalArgumentException(errorMsg); } return text; } public static Object[] notEmpty(Object[] array, String errorMsg) throws IllegalArgumentException { if (array == null || array.length == 0) { throw new IllegalArgumentException(errorMsg); } return array; } public static Collection notEmpty(Collection collection, String errorMsg) throws IllegalArgumentException { if (collection == null || collection.isEmpty()) { throw new IllegalArgumentException(errorMsg); } return collection; } public static Map notEmpty(Map map, String errorMsg) throws IllegalArgumentException { if (map == null || map.isEmpty()) { throw new IllegalArgumentException(errorMsg); } return map; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/MetaObjectUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2018 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import org.apache.ibatis.reflection.MetaObject; import tk.mybatis.mapper.MapperException; import java.lang.reflect.Method; /** * 来自 分页插件 PageHelper * * @author liuzh */ public class MetaObjectUtil { public static Method method; static { try { Class metaClass = Class.forName("org.apache.ibatis.reflection.SystemMetaObject"); method = metaClass.getDeclaredMethod("forObject", Object.class); } catch (Exception e1) { try { Class metaClass = Class.forName("org.apache.ibatis.reflection.MetaObject"); method = metaClass.getDeclaredMethod("forObject", Object.class); } catch (Exception e2) { throw new MapperException(e2); } } } public static MetaObject forObject(Object object) { try { return (MetaObject) method.invoke(null, object); } catch (Exception e) { throw new MapperException(e); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/MsUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.decorators.SoftCache; import org.apache.ibatis.cache.impl.PerpetualCache; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; /** * @author liuzh * @since 2017/7/9. */ public class MsUtil { public static final Cache CLASS_CACHE = new SoftCache(new PerpetualCache("MAPPER_CLASS_CACHE")); /** * 根据msId获取接口类 * * @param msId * @return */ public static Class getMapperClass(String msId) { if (msId.indexOf(".") == -1) { throw new MapperException("当前MappedStatement的id=" + msId + ",不符合MappedStatement的规则!"); } String mapperClassStr = msId.substring(0, msId.lastIndexOf(".")); //由于一个接口中的每个方法都会进行下面的操作,因此缓存 Class mapperClass = (Class) CLASS_CACHE.getObject(mapperClassStr); if (mapperClass != null) { return mapperClass; } ClassLoader[] classLoader = getClassLoaders(); for (ClassLoader cl : classLoader) { if (null != cl) { try { mapperClass = Class.forName(mapperClassStr, true, cl); if (mapperClass != null) { break; } } catch (ClassNotFoundException e) { // we'll ignore this until all class loaders fail to locate the class } } } if (mapperClass == null) { throw new MapperException("class loaders failed to locate the class " + mapperClassStr); } CLASS_CACHE.putObject(mapperClassStr, mapperClass); return mapperClass; } private static ClassLoader[] getClassLoaders() { return new ClassLoader[]{Thread.currentThread().getContextClassLoader(), MsUtil.class.getClassLoader()}; } /** * 获取执行的方法名 * * @param ms * @return */ public static String getMethodName(MappedStatement ms) { return getMethodName(ms.getId()); } /** * 获取执行的方法名 * * @param msId * @return */ public static String getMethodName(String msId) { return msId.substring(msId.lastIndexOf(".") + 1); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/OGNL.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.annotation.LogicDelete; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.IDynamicTableName; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.lang.reflect.Method; import java.util.*; /** * OGNL静态方法 * * @author liuzh */ public abstract class OGNL { public static final String SAFE_DELETE_ERROR = "通用 Mapper 安全检查: 对查询条件参数进行检查时出错!"; public static final String SAFE_DELETE_EXCEPTION = "通用 Mapper 安全检查: 当前操作的方法没有指定查询条件,不允许执行该操作!"; /** * 校验通用 Example 的 entityClass 和当前方法是否匹配 * * @param parameter * @param entityFullName * @return */ public static boolean checkExampleEntityClass(Object parameter, String entityFullName) { if (parameter != null && parameter instanceof Example && StringUtil.isNotEmpty(entityFullName)) { Example example = (Example) parameter; Class entityClass = example.getEntityClass(); if (!entityClass.getName().equals(entityFullName)) { throw new MapperException("当前 Example 方法对应实体为:" + entityFullName + ", 但是参数 Example 中的 entityClass 为:" + entityClass.getName()); } } return true; } /** * 检查 parameter 对象中指定的 fields 是否全是 null,如果是则抛出异常 * * @param parameter * @param fields * @return */ public static boolean notAllNullParameterCheck(Object parameter, String fields) { if (parameter != null) { try { Set columns = EntityHelper.getColumns(parameter.getClass()); Set fieldSet = new HashSet(Arrays.asList(fields.split(","))); for (EntityColumn column : columns) { if (fieldSet.contains(column.getProperty())) { Object value = column.getEntityField().getValue(parameter); if (value != null) { return true; } } } } catch (Exception e) { throw new MapperException(SAFE_DELETE_ERROR, e); } } throw new MapperException(SAFE_DELETE_EXCEPTION); } /** * 校验集合类型参数不能为空 * * @param parameter * @param error * @return */ public static boolean notEmptyCollectionCheck(Object parameter, String error) { if (parameter == null || (parameter instanceof Collection && ((Collection) parameter).size() == 0)) { throw new IllegalArgumentException(error); } return true; } /** * 检查 parameter 对象中指定的 fields 是否全是 null,如果是则抛出异常 * * @param parameter * @return */ public static boolean exampleHasAtLeastOneCriteriaCheck(Object parameter) { if (parameter != null) { try { if (parameter instanceof Example) { List criteriaList = ((Example) parameter).getOredCriteria(); if (criteriaList != null && criteriaList.size() > 0) { for (Example.Criteria criteria : criteriaList) { if (criteria != null && criteria.isValid()) { return true; } } } } else { Method getter = parameter.getClass().getDeclaredMethod("getOredCriteria"); Object list = getter.invoke(parameter); if (list != null && list instanceof List) { List criteriaList = (List) list; if (criteriaList.size() > 0) { for (Object criteria : criteriaList) { if (criteria instanceof Example.Criteria && ((Example.Criteria) criteria).isValid()) { return true; } } } } } } catch (Exception e) { throw new MapperException(SAFE_DELETE_ERROR, e); } } throw new MapperException(SAFE_DELETE_EXCEPTION); } /** * 是否包含自定义查询列 * * @param parameter * @return */ public static boolean hasSelectColumns(Object parameter) { if (parameter != null && parameter instanceof Example) { Example example = (Example) parameter; if (example.getSelectColumns() != null && example.getSelectColumns().size() > 0) { return true; } } return false; } /** * 是否包含自定义 Count 列 * * @param parameter * @return */ public static boolean hasCountColumn(Object parameter) { if (parameter != null && parameter instanceof Example) { Example example = (Example) parameter; return StringUtil.isNotEmpty(example.getCountColumn()); } return false; } /** * 是否包含 forUpdate * * @param parameter * @return */ public static boolean hasForUpdate(Object parameter) { if (parameter != null && parameter instanceof Example) { Example example = (Example) parameter; return example.isForUpdate(); } return false; } /** * 不包含自定义查询列 * * @param parameter * @return */ public static boolean hasNoSelectColumns(Object parameter) { return !hasSelectColumns(parameter); } /** * 判断参数是否支持动态表名 * * @param parameter * @return true支持,false不支持 */ public static boolean isDynamicParameter(Object parameter) { if (parameter != null && parameter instanceof IDynamicTableName) { return true; } return false; } /** * 判断参数是否b支持动态表名 * * @param parameter * @return true不支持,false支持 */ public static boolean isNotDynamicParameter(Object parameter) { return !isDynamicParameter(parameter); } /** * 判断条件是 and 还是 or * * @param parameter * @return */ public static String andOr(Object parameter) { if (parameter instanceof Example.Criteria) { return ((Example.Criteria) parameter).getAndOr(); } else if (parameter instanceof Example.Criterion) { return ((Example.Criterion) parameter).getAndOr(); } else if (parameter.getClass().getName().endsWith("Criteria")) { return "or"; } else { return "and"; } } /** * 拼接逻辑删除字段的未删除查询条件 * * @param parameter * @return */ public static String andNotLogicDelete(Object parameter) { String result = ""; if (parameter instanceof Example) { Example example = (Example) parameter; Map propertyMap = example.getPropertyMap(); for (Map.Entry entry : propertyMap.entrySet()) { EntityColumn column = entry.getValue(); if (column.getEntityField().isAnnotationPresent(LogicDelete.class)) { // 未逻辑删除的条件 Integer logicDeletedValue = SqlHelper.getLogicDeletedValue(column, false); if(logicDeletedValue==null){ result = column.getColumn() + " is null "; }else { result = column.getColumn() + " = " + logicDeletedValue; } // 如果Example中有条件,则拼接" and ", // 如果是空的oredCriteria,则where中只有逻辑删除注解的未删除条件 if (hasWhereCause(example)) { result += " and "; } } } } return result; } /** * 检查是否存在where条件,存在返回true,不存在返回false. * * @param example * @return */ private static boolean hasWhereCause(Example example) { if (example.getOredCriteria() == null || example.getOredCriteria().size() == 0) { return false; } for (Example.Criteria oredCriterion : example.getOredCriteria()) { if (oredCriterion.getAllCriteria().size() != 0) { return true; } } return false; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/SimpleTypeUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import tk.mybatis.mapper.MapperException; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Timestamp; import java.util.Date; import java.util.HashSet; import java.util.Set; /** * 参考 org.apache.ibatis.type.SimpleTypeRegistry */ public class SimpleTypeUtil { public static final String[] JAVA8_DATE_TIME = { "java.time.Instant", "java.time.LocalDateTime", "java.time.LocalDate", "java.time.LocalTime", "java.time.OffsetDateTime", "java.time.OffsetTime", "java.time.ZonedDateTime", "java.time.Year", "java.time.Month", "java.time.YearMonth" }; private static final Set> SIMPLE_TYPE_SET = new HashSet>(); /** * 特别注意:由于基本类型有默认值,因此在实体类中不建议使用基本类型作为数据库字段类型 */ static { SIMPLE_TYPE_SET.add(byte[].class); SIMPLE_TYPE_SET.add(String.class); SIMPLE_TYPE_SET.add(Byte.class); SIMPLE_TYPE_SET.add(Short.class); SIMPLE_TYPE_SET.add(Character.class); SIMPLE_TYPE_SET.add(Integer.class); SIMPLE_TYPE_SET.add(Long.class); SIMPLE_TYPE_SET.add(Float.class); SIMPLE_TYPE_SET.add(Double.class); SIMPLE_TYPE_SET.add(Boolean.class); SIMPLE_TYPE_SET.add(Date.class); SIMPLE_TYPE_SET.add(Timestamp.class); SIMPLE_TYPE_SET.add(Class.class); SIMPLE_TYPE_SET.add(BigInteger.class); SIMPLE_TYPE_SET.add(BigDecimal.class); //反射方式设置 java8 中的日期类型 for (String time : JAVA8_DATE_TIME) { registerSimpleTypeSilence(time); } } /** * 注册新的类型 * * @param clazz */ public static void registerSimpleType(Class clazz) { SIMPLE_TYPE_SET.add(clazz); } /** * 注册 8 种基本类型 */ public static void registerPrimitiveTypes() { registerSimpleType(boolean.class); registerSimpleType(byte.class); registerSimpleType(short.class); registerSimpleType(int.class); registerSimpleType(long.class); registerSimpleType(char.class); registerSimpleType(float.class); registerSimpleType(double.class); } /** * 注册新的类型 * * @param classes */ public static void registerSimpleType(String classes) { if (StringUtil.isNotEmpty(classes)) { String[] cls = classes.split(","); for (String c : cls) { try { SIMPLE_TYPE_SET.add(Class.forName(c)); } catch (ClassNotFoundException e) { throw new MapperException("注册类型出错:" + c, e); } } } } /** * 注册新的类型,不存在时不抛出异常 * * @param clazz */ private static void registerSimpleTypeSilence(String clazz) { try { SIMPLE_TYPE_SET.add(Class.forName(clazz)); } catch (ClassNotFoundException e) { //ignore } } /* * Tells us if the class passed in is a known common type * * @param clazz The class to check * @return True if the class is known */ public static boolean isSimpleType(Class clazz) { return SIMPLE_TYPE_SET.contains(clazz); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/SqlReservedWords.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import java.util.HashSet; import java.util.Set; /** * This class contains a somewhat comprehensive list of SQL reserved words. * Since different databases have different reserved words, this list is * inclusive of many different databases - so it may include words that are not * reserved in some databases. * *

This list is based on the list from Drupal Handbook: * http://drupal.org/node/141051 With additions for DB2 * * @author Jeff Butler */ public class SqlReservedWords { private static Set RESERVED_WORDS; static { String[] words = {"A", //$NON-NLS-1$ "ABORT", //$NON-NLS-1$ "ABS", //$NON-NLS-1$ "ABSOLUTE", //$NON-NLS-1$ "ACCESS", //$NON-NLS-1$ "ACTION", //$NON-NLS-1$ "ADA", //$NON-NLS-1$ "ADD", // DB2 //$NON-NLS-1$ "ADMIN", //$NON-NLS-1$ "AFTER", // DB2 //$NON-NLS-1$ "AGGREGATE", //$NON-NLS-1$ "ALIAS", // DB2 //$NON-NLS-1$ "ALL", // DB2 //$NON-NLS-1$ "ALLOCATE", // DB2 //$NON-NLS-1$ "ALLOW", // DB2 //$NON-NLS-1$ "ALSO", //$NON-NLS-1$ "ALTER", // DB2 //$NON-NLS-1$ "ALWAYS", //$NON-NLS-1$ "ANALYSE", //$NON-NLS-1$ "ANALYZE", //$NON-NLS-1$ "AND", // DB2 //$NON-NLS-1$ "ANY", // DB2 //$NON-NLS-1$ "APPLICATION", // DB2 //$NON-NLS-1$ "ARE", //$NON-NLS-1$ "ARRAY", //$NON-NLS-1$ "AS", // DB2 //$NON-NLS-1$ "ASC", //$NON-NLS-1$ "ASENSITIVE", //$NON-NLS-1$ "ASSERTION", //$NON-NLS-1$ "ASSIGNMENT", //$NON-NLS-1$ "ASSOCIATE", // DB2 //$NON-NLS-1$ "ASUTIME", // DB2 //$NON-NLS-1$ "ASYMMETRIC", //$NON-NLS-1$ "AT", //$NON-NLS-1$ "ATOMIC", //$NON-NLS-1$ "ATTRIBUTE", //$NON-NLS-1$ "ATTRIBUTES", //$NON-NLS-1$ "AUDIT", // DB2 //$NON-NLS-1$ "AUTHORIZATION", // DB2 //$NON-NLS-1$ "AUTO_INCREMENT", //$NON-NLS-1$ "AUX", // DB2 //$NON-NLS-1$ "AUXILIARY", // DB2 //$NON-NLS-1$ "AVG", //$NON-NLS-1$ "AVG_ROW_LENGTH", //$NON-NLS-1$ "BACKUP", //$NON-NLS-1$ "BACKWARD", //$NON-NLS-1$ "BEFORE", // DB2 //$NON-NLS-1$ "BEGIN", // DB2 //$NON-NLS-1$ "BERNOULLI", //$NON-NLS-1$ "BETWEEN", // DB2 //$NON-NLS-1$ "BIGINT", //$NON-NLS-1$ "BINARY", // DB2 //$NON-NLS-1$ "BIT", //$NON-NLS-1$ "BIT_LENGTH", //$NON-NLS-1$ "BITVAR", //$NON-NLS-1$ "BLOB", //$NON-NLS-1$ "BOOL", //$NON-NLS-1$ "BOOLEAN", //$NON-NLS-1$ "BOTH", //$NON-NLS-1$ "BREADTH", //$NON-NLS-1$ "BREAK", //$NON-NLS-1$ "BROWSE", //$NON-NLS-1$ "BUFFERPOOL", // DB2 //$NON-NLS-1$ "BULK", //$NON-NLS-1$ "BY", // DB2 //$NON-NLS-1$ "C", //$NON-NLS-1$ "CACHE", // DB2 //$NON-NLS-1$ "CALL", // DB2 //$NON-NLS-1$ "CALLED", // DB2 //$NON-NLS-1$ "CAPTURE", // DB2 //$NON-NLS-1$ "CARDINALITY", // DB2 //$NON-NLS-1$ "CASCADE", //$NON-NLS-1$ "CASCADED", // DB2 //$NON-NLS-1$ "CASE", // DB2 //$NON-NLS-1$ "CAST", // DB2 //$NON-NLS-1$ "CATALOG", //$NON-NLS-1$ "CATALOG_NAME", //$NON-NLS-1$ "CCSID", // DB2 //$NON-NLS-1$ "CEIL", //$NON-NLS-1$ "CEILING", //$NON-NLS-1$ "CHAIN", //$NON-NLS-1$ "CHANGE", //$NON-NLS-1$ "CHAR", // DB2 //$NON-NLS-1$ "CHAR_LENGTH", //$NON-NLS-1$ "CHARACTER", // DB2 //$NON-NLS-1$ "CHARACTER_LENGTH", //$NON-NLS-1$ "CHARACTER_SET_CATALOG", //$NON-NLS-1$ "CHARACTER_SET_NAME", //$NON-NLS-1$ "CHARACTER_SET_SCHEMA", //$NON-NLS-1$ "CHARACTERISTICS", //$NON-NLS-1$ "CHARACTERS", //$NON-NLS-1$ "CHECK", // DB2 //$NON-NLS-1$ "CHECKED", //$NON-NLS-1$ "CHECKPOINT", //$NON-NLS-1$ "CHECKSUM", //$NON-NLS-1$ "CLASS", //$NON-NLS-1$ "CLASS_ORIGIN", //$NON-NLS-1$ "CLOB", //$NON-NLS-1$ "CLOSE", // DB2 //$NON-NLS-1$ "CLUSTER", // DB2 //$NON-NLS-1$ "CLUSTERED", //$NON-NLS-1$ "COALESCE", //$NON-NLS-1$ "COBOL", //$NON-NLS-1$ "COLLATE", //$NON-NLS-1$ "COLLATION", //$NON-NLS-1$ "COLLATION_CATALOG", //$NON-NLS-1$ "COLLATION_NAME", //$NON-NLS-1$ "COLLATION_SCHEMA", //$NON-NLS-1$ "COLLECT", //$NON-NLS-1$ "COLLECTION", // DB2 //$NON-NLS-1$ "COLLID", // DB2 //$NON-NLS-1$ "COLUMN", // DB2 //$NON-NLS-1$ "COLUMN_NAME", //$NON-NLS-1$ "COLUMNS", //$NON-NLS-1$ "COMMAND_FUNCTION", //$NON-NLS-1$ "COMMAND_FUNCTION_CODE", //$NON-NLS-1$ "COMMENT", // DB2 //$NON-NLS-1$ "COMMIT", // DB2 //$NON-NLS-1$ "COMMITTED", //$NON-NLS-1$ "COMPLETION", //$NON-NLS-1$ "COMPRESS", //$NON-NLS-1$ "COMPUTE", //$NON-NLS-1$ "CONCAT", // DB2 //$NON-NLS-1$ "CONDITION", // DB2 //$NON-NLS-1$ "CONDITION_NUMBER", //$NON-NLS-1$ "CONNECT", // DB2 //$NON-NLS-1$ "CONNECTION", // DB2 //$NON-NLS-1$ "CONNECTION_NAME", //$NON-NLS-1$ "CONSTRAINT", // DB2 //$NON-NLS-1$ "CONSTRAINT_CATALOG", //$NON-NLS-1$ "CONSTRAINT_NAME", //$NON-NLS-1$ "CONSTRAINT_SCHEMA", //$NON-NLS-1$ "CONSTRAINTS", //$NON-NLS-1$ "CONSTRUCTOR", //$NON-NLS-1$ "CONTAINS", // DB2 //$NON-NLS-1$ "CONTAINSTABLE", //$NON-NLS-1$ "CONTINUE", // DB2 //$NON-NLS-1$ "CONVERSION", //$NON-NLS-1$ "CONVERT", //$NON-NLS-1$ "COPY", //$NON-NLS-1$ "CORR", //$NON-NLS-1$ "CORRESPONDING", //$NON-NLS-1$ "COUNT", // DB2 //$NON-NLS-1$ "COUNT_BIG", // DB2 //$NON-NLS-1$ "COVAR_POP", //$NON-NLS-1$ "COVAR_SAMP", //$NON-NLS-1$ "CREATE", // DB2 //$NON-NLS-1$ "CREATEDB", //$NON-NLS-1$ "CREATEROLE", //$NON-NLS-1$ "CREATEUSER", //$NON-NLS-1$ "CROSS", // DB2 //$NON-NLS-1$ "CSV", //$NON-NLS-1$ "CUBE", //$NON-NLS-1$ "CUME_DIST", //$NON-NLS-1$ "CURRENT", // DB2 //$NON-NLS-1$ "CURRENT_DATE", // DB2 //$NON-NLS-1$ "CURRENT_DEFAULT_TRANSFORM_GROUP", //$NON-NLS-1$ "CURRENT_LC_CTYPE", // DB2 //$NON-NLS-1$ "CURRENT_PATH", // DB2 //$NON-NLS-1$ "CURRENT_ROLE", //$NON-NLS-1$ "CURRENT_SERVER", // DB2 //$NON-NLS-1$ "CURRENT_TIME", // DB2 //$NON-NLS-1$ "CURRENT_TIMESTAMP", // DB2 //$NON-NLS-1$ "CURRENT_TIMEZONE", // DB2 //$NON-NLS-1$ "CURRENT_TRANSFORM_GROUP_FOR_TYPE", //$NON-NLS-1$ "CURRENT_USER", // DB2 //$NON-NLS-1$ "CURSOR", // DB2 //$NON-NLS-1$ "CURSOR_NAME", //$NON-NLS-1$ "CYCLE", // DB2 //$NON-NLS-1$ "DATA", // DB2 //$NON-NLS-1$ "DATABASE", // DB2 //$NON-NLS-1$ "DATABASES", //$NON-NLS-1$ "DATE", //$NON-NLS-1$ "DATETIME", //$NON-NLS-1$ "DATETIME_INTERVAL_CODE", //$NON-NLS-1$ "DATETIME_INTERVAL_PRECISION", //$NON-NLS-1$ "DAY", // DB2 //$NON-NLS-1$ "DAY_HOUR", //$NON-NLS-1$ "DAY_MICROSECOND", //$NON-NLS-1$ "DAY_MINUTE", //$NON-NLS-1$ "DAY_SECOND", //$NON-NLS-1$ "DAYOFMONTH", //$NON-NLS-1$ "DAYOFWEEK", //$NON-NLS-1$ "DAYOFYEAR", //$NON-NLS-1$ "DAYS", // DB2 //$NON-NLS-1$ "DB2GENERAL", // DB2 //$NON-NLS-1$ "DB2GNRL", // DB2 //$NON-NLS-1$ "DB2SQL", // DB2 //$NON-NLS-1$ "DBCC", //$NON-NLS-1$ "DBINFO", // DB2 //$NON-NLS-1$ "DEALLOCATE", //$NON-NLS-1$ "DEC", //$NON-NLS-1$ "DECIMAL", //$NON-NLS-1$ "DECLARE", // DB2 //$NON-NLS-1$ "DEFAULT", // DB2 //$NON-NLS-1$ "DEFAULTS", // DB2 //$NON-NLS-1$ "DEFERRABLE", //$NON-NLS-1$ "DEFERRED", //$NON-NLS-1$ "DEFINED", //$NON-NLS-1$ "DEFINER", //$NON-NLS-1$ "DEFINITION", // DB2 //$NON-NLS-1$ "DEGREE", //$NON-NLS-1$ "DELAY_KEY_WRITE", //$NON-NLS-1$ "DELAYED", //$NON-NLS-1$ "DELETE", // DB2 //$NON-NLS-1$ "DELIMITER", //$NON-NLS-1$ "DELIMITERS", //$NON-NLS-1$ "DENSE_RANK", //$NON-NLS-1$ "DENY", //$NON-NLS-1$ "DEPTH", //$NON-NLS-1$ "DEREF", //$NON-NLS-1$ "DERIVED", //$NON-NLS-1$ "DESC", //$NON-NLS-1$ "DESCRIBE", //$NON-NLS-1$ "DESCRIPTOR", // DB2 //$NON-NLS-1$ "DESTROY", //$NON-NLS-1$ "DESTRUCTOR", //$NON-NLS-1$ "DETERMINISTIC", // DB2 //$NON-NLS-1$ "DIAGNOSTICS", //$NON-NLS-1$ "DICTIONARY", //$NON-NLS-1$ "DISABLE", //$NON-NLS-1$ "DISALLOW", // DB2 //$NON-NLS-1$ "DISCONNECT", // DB2 //$NON-NLS-1$ "DISK", //$NON-NLS-1$ "DISPATCH", //$NON-NLS-1$ "DISTINCT", // DB2 //$NON-NLS-1$ "DISTINCTROW", //$NON-NLS-1$ "DISTRIBUTED", //$NON-NLS-1$ "DIV", //$NON-NLS-1$ "DO", // DB2 //$NON-NLS-1$ "DOMAIN", //$NON-NLS-1$ "DOUBLE", // DB2 //$NON-NLS-1$ "DROP", // DB2 //$NON-NLS-1$ "DSNHATTR", // DB2 //$NON-NLS-1$ "DSSIZE", // DB2 //$NON-NLS-1$ "DUAL", //$NON-NLS-1$ "DUMMY", //$NON-NLS-1$ "DUMP", //$NON-NLS-1$ "DYNAMIC", // DB2 //$NON-NLS-1$ "DYNAMIC_FUNCTION", //$NON-NLS-1$ "DYNAMIC_FUNCTION_CODE", //$NON-NLS-1$ "EACH", // DB2 //$NON-NLS-1$ "EDITPROC", // DB2 //$NON-NLS-1$ "ELEMENT", //$NON-NLS-1$ "ELSE", // DB2 //$NON-NLS-1$ "ELSEIF", // DB2 //$NON-NLS-1$ "ENABLE", //$NON-NLS-1$ "ENCLOSED", //$NON-NLS-1$ "ENCODING", // DB2 //$NON-NLS-1$ "ENCRYPTED", //$NON-NLS-1$ "END", // DB2 //$NON-NLS-1$ "END-EXEC", // DB2 //$NON-NLS-1$ "END-EXEC1", // DB2 //$NON-NLS-1$ "ENUM", //$NON-NLS-1$ "EQUALS", //$NON-NLS-1$ "ERASE", // DB2 //$NON-NLS-1$ "ERRLVL", //$NON-NLS-1$ "ESCAPE", // DB2 //$NON-NLS-1$ "ESCAPED", //$NON-NLS-1$ "EVERY", //$NON-NLS-1$ "EXCEPT", // DB2 //$NON-NLS-1$ "EXCEPTION", // DB2 //$NON-NLS-1$ "EXCLUDE", //$NON-NLS-1$ "EXCLUDING", // DB2 //$NON-NLS-1$ "EXCLUSIVE", //$NON-NLS-1$ "EXEC", //$NON-NLS-1$ "EXECUTE", // DB2 //$NON-NLS-1$ "EXISTING", //$NON-NLS-1$ "EXISTS", // DB2 //$NON-NLS-1$ "EXIT", // DB2 //$NON-NLS-1$ "EXP", //$NON-NLS-1$ "EXPLAIN", //$NON-NLS-1$ "EXTERNAL", // DB2 //$NON-NLS-1$ "EXTRACT", //$NON-NLS-1$ "FALSE", //$NON-NLS-1$ "FENCED", // DB2 //$NON-NLS-1$ "FETCH", // DB2 //$NON-NLS-1$ "FIELDPROC", // DB2 //$NON-NLS-1$ "FIELDS", //$NON-NLS-1$ "FILE", // DB2 //$NON-NLS-1$ "FILLFACTOR", //$NON-NLS-1$ "FILTER", //$NON-NLS-1$ "FINAL", // DB2 //$NON-NLS-1$ "FIRST", //$NON-NLS-1$ "FLOAT", //$NON-NLS-1$ "FLOAT4", //$NON-NLS-1$ "FLOAT8", //$NON-NLS-1$ "FLOOR", //$NON-NLS-1$ "FLUSH", //$NON-NLS-1$ "FOLLOWING", //$NON-NLS-1$ "FOR", // DB2 //$NON-NLS-1$ "FORCE", //$NON-NLS-1$ "FOREIGN", // DB2 //$NON-NLS-1$ "FORTRAN", //$NON-NLS-1$ "FORWARD", //$NON-NLS-1$ "FOUND", //$NON-NLS-1$ "FREE", // DB2 //$NON-NLS-1$ "FREETEXT", //$NON-NLS-1$ "FREETEXTTABLE", //$NON-NLS-1$ "FREEZE", //$NON-NLS-1$ "FROM", // DB2 //$NON-NLS-1$ "FULL", // DB2 //$NON-NLS-1$ "FULLTEXT", //$NON-NLS-1$ "FUNCTION", // DB2 //$NON-NLS-1$ "FUSION", //$NON-NLS-1$ "G", //$NON-NLS-1$ "GENERAL", // DB2 //$NON-NLS-1$ "GENERATED", // DB2 //$NON-NLS-1$ "GET", // DB2 //$NON-NLS-1$ "GLOBAL", // DB2 //$NON-NLS-1$ "GO", // DB2 //$NON-NLS-1$ "GOTO", // DB2 //$NON-NLS-1$ "GRANT", // DB2 //$NON-NLS-1$ "GRANTED", //$NON-NLS-1$ "GRANTS", //$NON-NLS-1$ "GRAPHIC", // DB2 //$NON-NLS-1$ "GREATEST", //$NON-NLS-1$ "GROUP", // DB2 //$NON-NLS-1$ "GROUPING", //$NON-NLS-1$ "HANDLER", // DB2 //$NON-NLS-1$ "HAVING", // DB2 //$NON-NLS-1$ "HEADER", //$NON-NLS-1$ "HEAP", //$NON-NLS-1$ "HIERARCHY", //$NON-NLS-1$ "HIGH_PRIORITY", //$NON-NLS-1$ "HOLD", // DB2 //$NON-NLS-1$ "HOLDLOCK", //$NON-NLS-1$ "HOST", //$NON-NLS-1$ "HOSTS", //$NON-NLS-1$ "HOUR", // DB2 //$NON-NLS-1$ "HOUR_MICROSECOND", //$NON-NLS-1$ "HOUR_MINUTE", //$NON-NLS-1$ "HOUR_SECOND", //$NON-NLS-1$ "HOURS", // DB2 //$NON-NLS-1$ "IDENTIFIED", //$NON-NLS-1$ "IDENTITY", // DB2 //$NON-NLS-1$ "IDENTITY_INSERT", //$NON-NLS-1$ "IDENTITYCOL", //$NON-NLS-1$ "IF", // DB2 //$NON-NLS-1$ "IGNORE", //$NON-NLS-1$ "ILIKE", //$NON-NLS-1$ "IMMEDIATE", // DB2 //$NON-NLS-1$ "IMMUTABLE", //$NON-NLS-1$ "IMPLEMENTATION", //$NON-NLS-1$ "IMPLICIT", //$NON-NLS-1$ "IN", // DB2 //$NON-NLS-1$ "INCLUDE", //$NON-NLS-1$ "INCLUDING", // DB2 //$NON-NLS-1$ "INCREMENT", // DB2 //$NON-NLS-1$ "INDEX", // DB2 //$NON-NLS-1$ "INDICATOR", // DB2 //$NON-NLS-1$ "INFILE", //$NON-NLS-1$ "INFIX", //$NON-NLS-1$ "INHERIT", // DB2 //$NON-NLS-1$ "INHERITS", //$NON-NLS-1$ "INITIAL", //$NON-NLS-1$ "INITIALIZE", //$NON-NLS-1$ "INITIALLY", //$NON-NLS-1$ "INNER", // DB2 //$NON-NLS-1$ "INOUT", // DB2 //$NON-NLS-1$ "INPUT", //$NON-NLS-1$ "INSENSITIVE", // DB2 //$NON-NLS-1$ "INSERT", // DB2 //$NON-NLS-1$ "INSERT_ID", //$NON-NLS-1$ "INSTANCE", //$NON-NLS-1$ "INSTANTIABLE", //$NON-NLS-1$ "INSTEAD", //$NON-NLS-1$ "INT", //$NON-NLS-1$ "INT1", //$NON-NLS-1$ "INT2", //$NON-NLS-1$ "INT3", //$NON-NLS-1$ "INT4", //$NON-NLS-1$ "INT8", //$NON-NLS-1$ "INTEGER", //$NON-NLS-1$ "INTEGRITY", // DB2 //$NON-NLS-1$ "INTERSECT", //$NON-NLS-1$ "INTERSECTION", //$NON-NLS-1$ "INTERVAL", //$NON-NLS-1$ "INTO", // DB2 //$NON-NLS-1$ "INVOKER", //$NON-NLS-1$ "IS", // DB2 //$NON-NLS-1$ "ISAM", //$NON-NLS-1$ "ISNULL", //$NON-NLS-1$ "ISOBID", // DB2 //$NON-NLS-1$ "ISOLATION", // DB2 //$NON-NLS-1$ "ITERATE", // DB2 //$NON-NLS-1$ "JAR", // DB2 //$NON-NLS-1$ "JAVA", // DB2 //$NON-NLS-1$ "JOIN", // DB2 //$NON-NLS-1$ "K", //$NON-NLS-1$ "KEY", // DB2 //$NON-NLS-1$ "KEY_MEMBER", //$NON-NLS-1$ "KEY_TYPE", //$NON-NLS-1$ "KEYS", //$NON-NLS-1$ "KILL", //$NON-NLS-1$ "LABEL", // DB2 //$NON-NLS-1$ "LANCOMPILER", //$NON-NLS-1$ "LANGUAGE", // DB2 //$NON-NLS-1$ "LARGE", //$NON-NLS-1$ "LAST", //$NON-NLS-1$ "LAST_INSERT_ID", //$NON-NLS-1$ "LATERAL", //$NON-NLS-1$ "LC_CTYPE", // DB2 //$NON-NLS-1$ "LEADING", //$NON-NLS-1$ "LEAST", //$NON-NLS-1$ "LEAVE", // DB2 //$NON-NLS-1$ "LEFT", // DB2 //$NON-NLS-1$ "LENGTH", //$NON-NLS-1$ "LESS", //$NON-NLS-1$ "LEVEL", //$NON-NLS-1$ "LIKE", // DB2 //$NON-NLS-1$ "LIMIT", //$NON-NLS-1$ "LINENO", //$NON-NLS-1$ "LINES", //$NON-NLS-1$ "LINKTYPE", // DB2 //$NON-NLS-1$ "LISTEN", //$NON-NLS-1$ "LN", //$NON-NLS-1$ "LOAD", //$NON-NLS-1$ "LOCAL", // DB2 //$NON-NLS-1$ "LOCALE", // DB2 //$NON-NLS-1$ "LOCALTIME", //$NON-NLS-1$ "LOCALTIMESTAMP", //$NON-NLS-1$ "LOCATION", //$NON-NLS-1$ "LOCATOR", // DB2 //$NON-NLS-1$ "LOCATORS", // DB2 //$NON-NLS-1$ "LOCK", // DB2 //$NON-NLS-1$ "LOCKMAX", // DB2 //$NON-NLS-1$ "LOCKSIZE", // DB2 //$NON-NLS-1$ "LOGIN", //$NON-NLS-1$ "LOGS", //$NON-NLS-1$ "LONG", // DB2 //$NON-NLS-1$ "LONGBLOB", //$NON-NLS-1$ "LONGTEXT", //$NON-NLS-1$ "LOOP", // DB2 //$NON-NLS-1$ "LOW_PRIORITY", //$NON-NLS-1$ "LOWER", //$NON-NLS-1$ "M", //$NON-NLS-1$ "MAP", //$NON-NLS-1$ "MATCH", //$NON-NLS-1$ "MATCHED", //$NON-NLS-1$ "MAX", //$NON-NLS-1$ "MAX_ROWS", //$NON-NLS-1$ "MAXEXTENTS", //$NON-NLS-1$ "MAXVALUE", // DB2 //$NON-NLS-1$ "MEDIUMBLOB", //$NON-NLS-1$ "MEDIUMINT", //$NON-NLS-1$ "MEDIUMTEXT", //$NON-NLS-1$ "MEMBER", //$NON-NLS-1$ "MERGE", //$NON-NLS-1$ "MESSAGE_LENGTH", //$NON-NLS-1$ "MESSAGE_OCTET_LENGTH", //$NON-NLS-1$ "MESSAGE_TEXT", //$NON-NLS-1$ "METHOD", //$NON-NLS-1$ "MICROSECOND", // DB2 //$NON-NLS-1$ "MICROSECONDS", // DB2 //$NON-NLS-1$ "MIDDLEINT", //$NON-NLS-1$ "MIN", //$NON-NLS-1$ "MIN_ROWS", //$NON-NLS-1$ "MINUS", //$NON-NLS-1$ "MINUTE", // DB2 //$NON-NLS-1$ "MINUTE_MICROSECOND", //$NON-NLS-1$ "MINUTE_SECOND", //$NON-NLS-1$ "MINUTES", // DB2 //$NON-NLS-1$ "MINVALUE", // DB2 //$NON-NLS-1$ "MLSLABEL", //$NON-NLS-1$ "MOD", //$NON-NLS-1$ "MODE", // DB2 //$NON-NLS-1$ "MODIFIES", // DB2 //$NON-NLS-1$ "MODIFY", //$NON-NLS-1$ "MODULE", //$NON-NLS-1$ "MONTH", // DB2 //$NON-NLS-1$ "MONTHNAME", //$NON-NLS-1$ "MONTHS", // DB2 //$NON-NLS-1$ "MORE", //$NON-NLS-1$ "MOVE", //$NON-NLS-1$ "MULTISET", //$NON-NLS-1$ "MUMPS", //$NON-NLS-1$ "MYISAM", //$NON-NLS-1$ "NAME", //$NON-NLS-1$ "NAMES", //$NON-NLS-1$ "NATIONAL", //$NON-NLS-1$ "NATURAL", //$NON-NLS-1$ "NCHAR", //$NON-NLS-1$ "NCLOB", //$NON-NLS-1$ "NESTING", //$NON-NLS-1$ "NEW", // DB2 //$NON-NLS-1$ "NEW_TABLE", // DB2 //$NON-NLS-1$ "NEXT", //$NON-NLS-1$ "NO", // DB2 //$NON-NLS-1$ "NO_WRITE_TO_BINLOG", //$NON-NLS-1$ "NOAUDIT", //$NON-NLS-1$ "NOCACHE", // DB2 //$NON-NLS-1$ "NOCHECK", //$NON-NLS-1$ "NOCOMPRESS", //$NON-NLS-1$ "NOCREATEDB", //$NON-NLS-1$ "NOCREATEROLE", //$NON-NLS-1$ "NOCREATEUSER", //$NON-NLS-1$ "NOCYCLE", // DB2 //$NON-NLS-1$ "NODENAME", // DB2 //$NON-NLS-1$ "NODENUMBER", // DB2 //$NON-NLS-1$ "NOINHERIT", //$NON-NLS-1$ "NOLOGIN", //$NON-NLS-1$ "NOMAXVALUE", // DB2 //$NON-NLS-1$ "NOMINVALUE", // DB2 //$NON-NLS-1$ "NONCLUSTERED", //$NON-NLS-1$ "NONE", //$NON-NLS-1$ "NOORDER", // DB2 //$NON-NLS-1$ "NORMALIZE", //$NON-NLS-1$ "NORMALIZED", //$NON-NLS-1$ "NOSUPERUSER", //$NON-NLS-1$ "NOT", // DB2 //$NON-NLS-1$ "NOTHING", //$NON-NLS-1$ "NOTIFY", //$NON-NLS-1$ "NOTNULL", //$NON-NLS-1$ "NOWAIT", //$NON-NLS-1$ "NULL", // DB2 //$NON-NLS-1$ "NULLABLE", //$NON-NLS-1$ "NULLIF", //$NON-NLS-1$ "NULLS", // DB2 //$NON-NLS-1$ "NUMBER", //$NON-NLS-1$ "NUMERIC", //$NON-NLS-1$ "NUMPARTS", // DB2 //$NON-NLS-1$ "OBID", // DB2 //$NON-NLS-1$ "OBJECT", //$NON-NLS-1$ "OCTET_LENGTH", //$NON-NLS-1$ "OCTETS", //$NON-NLS-1$ "OF", // DB2 //$NON-NLS-1$ "OFF", //$NON-NLS-1$ "OFFLINE", //$NON-NLS-1$ "OFFSET", //$NON-NLS-1$ "OFFSETS", //$NON-NLS-1$ "OIDS", //$NON-NLS-1$ "OLD", // DB2 //$NON-NLS-1$ "OLD_TABLE", // DB2 //$NON-NLS-1$ "ON", // DB2 //$NON-NLS-1$ "ONLINE", //$NON-NLS-1$ "ONLY", //$NON-NLS-1$ "OPEN", // DB2 //$NON-NLS-1$ "OPENDATASOURCE", //$NON-NLS-1$ "OPENQUERY", //$NON-NLS-1$ "OPENROWSET", //$NON-NLS-1$ "OPENXML", //$NON-NLS-1$ "OPERATION", //$NON-NLS-1$ "OPERATOR", //$NON-NLS-1$ "OPTIMIZATION", // DB2 //$NON-NLS-1$ "OPTIMIZE", // DB2 //$NON-NLS-1$ "OPTION", // DB2 //$NON-NLS-1$ "OPTIONALLY", //$NON-NLS-1$ "OPTIONS", //$NON-NLS-1$ "OR", // DB2 //$NON-NLS-1$ "ORDER", // DB2 //$NON-NLS-1$ "ORDERING", //$NON-NLS-1$ "ORDINALITY", //$NON-NLS-1$ "OTHERS", //$NON-NLS-1$ "OUT", // DB2 //$NON-NLS-1$ "OUTER", // DB2 //$NON-NLS-1$ "OUTFILE", //$NON-NLS-1$ "OUTPUT", //$NON-NLS-1$ "OVER", //$NON-NLS-1$ "OVERLAPS", //$NON-NLS-1$ "OVERLAY", //$NON-NLS-1$ "OVERRIDING", // DB2 //$NON-NLS-1$ "OWNER", //$NON-NLS-1$ "PACK_KEYS", //$NON-NLS-1$ "PACKAGE", // DB2 //$NON-NLS-1$ "PAD", //$NON-NLS-1$ "PARAMETER", // DB2 //$NON-NLS-1$ "PARAMETER_MODE", //$NON-NLS-1$ "PARAMETER_NAME", //$NON-NLS-1$ "PARAMETER_ORDINAL_POSITION", //$NON-NLS-1$ "PARAMETER_SPECIFIC_CATALOG", //$NON-NLS-1$ "PARAMETER_SPECIFIC_NAME", //$NON-NLS-1$ "PARAMETER_SPECIFIC_SCHEMA", //$NON-NLS-1$ "PARAMETERS", //$NON-NLS-1$ "PART", // DB2 //$NON-NLS-1$ "PARTIAL", //$NON-NLS-1$ "PARTITION", // DB2 //$NON-NLS-1$ "PASCAL", //$NON-NLS-1$ "PASSWORD", //$NON-NLS-1$ "PATH", // DB2 //$NON-NLS-1$ "PCTFREE", //$NON-NLS-1$ "PERCENT", //$NON-NLS-1$ "PERCENT_RANK", //$NON-NLS-1$ "PERCENTILE_CONT", //$NON-NLS-1$ "PERCENTILE_DISC", //$NON-NLS-1$ "PIECESIZE", // DB2 //$NON-NLS-1$ "PLACING", //$NON-NLS-1$ "PLAN", // DB2 //$NON-NLS-1$ "PLI", //$NON-NLS-1$ "POSITION", // DB2 //$NON-NLS-1$ "POSTFIX", //$NON-NLS-1$ "POWER", //$NON-NLS-1$ "PRECEDING", //$NON-NLS-1$ "PRECISION", // DB2 //$NON-NLS-1$ "PREFIX", //$NON-NLS-1$ "PREORDER", //$NON-NLS-1$ "PREPARE", // DB2 //$NON-NLS-1$ "PREPARED", //$NON-NLS-1$ "PRESERVE", //$NON-NLS-1$ "PRIMARY", // DB2 //$NON-NLS-1$ "PRINT", //$NON-NLS-1$ "PRIOR", //$NON-NLS-1$ "PRIQTY", // DB2 //$NON-NLS-1$ "PRIVILEGES", // DB2 //$NON-NLS-1$ "PROC", //$NON-NLS-1$ "PROCEDURAL", //$NON-NLS-1$ "PROCEDURE", // DB2 //$NON-NLS-1$ "PROCESS", //$NON-NLS-1$ "PROCESSLIST", //$NON-NLS-1$ "PROGRAM", // DB2 //$NON-NLS-1$ "PSID", // DB2 //$NON-NLS-1$ "PUBLIC", //$NON-NLS-1$ "PURGE", //$NON-NLS-1$ "QUERYNO", // DB2 //$NON-NLS-1$ "QUOTE", //$NON-NLS-1$ "RAID0", //$NON-NLS-1$ "RAISERROR", //$NON-NLS-1$ "RANGE", //$NON-NLS-1$ "RANK", //$NON-NLS-1$ "RAW", //$NON-NLS-1$ "READ", // DB2 //$NON-NLS-1$ "READS", // DB2 //$NON-NLS-1$ "READTEXT", //$NON-NLS-1$ "REAL", //$NON-NLS-1$ "RECHECK", //$NON-NLS-1$ "RECONFIGURE", //$NON-NLS-1$ "RECOVERY", // DB2 //$NON-NLS-1$ "RECURSIVE", //$NON-NLS-1$ "REF", //$NON-NLS-1$ "REFERENCES", // DB2 //$NON-NLS-1$ "REFERENCING", // DB2 //$NON-NLS-1$ "REGEXP", //$NON-NLS-1$ "REGR_AVGX", //$NON-NLS-1$ "REGR_AVGY", //$NON-NLS-1$ "REGR_COUNT", //$NON-NLS-1$ "REGR_INTERCEPT", //$NON-NLS-1$ "REGR_R2", //$NON-NLS-1$ "REGR_SLOPE", //$NON-NLS-1$ "REGR_SXX", //$NON-NLS-1$ "REGR_SXY", //$NON-NLS-1$ "REGR_SYY", //$NON-NLS-1$ "REINDEX", //$NON-NLS-1$ "RELATIVE", //$NON-NLS-1$ "RELEASE", // DB2 //$NON-NLS-1$ "RELOAD", //$NON-NLS-1$ "RENAME", // DB2 //$NON-NLS-1$ "REPEAT", // DB2 //$NON-NLS-1$ "REPEATABLE", //$NON-NLS-1$ "REPLACE", //$NON-NLS-1$ "REPLICATION", //$NON-NLS-1$ "REQUIRE", //$NON-NLS-1$ "RESET", // DB2 //$NON-NLS-1$ "RESIGNAL", // DB2 //$NON-NLS-1$ "RESOURCE", //$NON-NLS-1$ "RESTART", // DB2 //$NON-NLS-1$ "RESTORE", //$NON-NLS-1$ "RESTRICT", // DB2 //$NON-NLS-1$ "RESULT", // DB2 //$NON-NLS-1$ "RESULT_SET_LOCATOR", // DB2 //$NON-NLS-1$ "RETURN", // DB2 //$NON-NLS-1$ "RETURNED_CARDINALITY", //$NON-NLS-1$ "RETURNED_LENGTH", //$NON-NLS-1$ "RETURNED_OCTET_LENGTH", //$NON-NLS-1$ "RETURNED_SQLSTATE", //$NON-NLS-1$ "RETURNS", // DB2 //$NON-NLS-1$ "REVOKE", // DB2 //$NON-NLS-1$ "RIGHT", // DB2 //$NON-NLS-1$ "RLIKE", //$NON-NLS-1$ "ROLE", //$NON-NLS-1$ "ROLLBACK", // DB2 //$NON-NLS-1$ "ROLLUP", //$NON-NLS-1$ "ROUTINE", // DB2 //$NON-NLS-1$ "ROUTINE_CATALOG", //$NON-NLS-1$ "ROUTINE_NAME", //$NON-NLS-1$ "ROUTINE_SCHEMA", //$NON-NLS-1$ "ROW", // DB2 //$NON-NLS-1$ "ROW_COUNT", //$NON-NLS-1$ "ROW_NUMBER", //$NON-NLS-1$ "ROWCOUNT", //$NON-NLS-1$ "ROWGUIDCOL", //$NON-NLS-1$ "ROWID", //$NON-NLS-1$ "ROWNUM", //$NON-NLS-1$ "ROWS", // DB2 //$NON-NLS-1$ "RRN", // DB2 //$NON-NLS-1$ "RULE", //$NON-NLS-1$ "RUN", // DB2 //$NON-NLS-1$ "SAVE", //$NON-NLS-1$ "SAVEPOINT", // DB2 //$NON-NLS-1$ "SCALE", //$NON-NLS-1$ "SCHEMA", // DB2 //$NON-NLS-1$ "SCHEMA_NAME", //$NON-NLS-1$ "SCHEMAS", //$NON-NLS-1$ "SCOPE", //$NON-NLS-1$ "SCOPE_CATALOG", //$NON-NLS-1$ "SCOPE_NAME", //$NON-NLS-1$ "SCOPE_SCHEMA", //$NON-NLS-1$ "SCRATCHPAD", // DB2 //$NON-NLS-1$ "SCROLL", //$NON-NLS-1$ "SEARCH", //$NON-NLS-1$ "SECOND", // DB2 //$NON-NLS-1$ "SECOND_MICROSECOND", //$NON-NLS-1$ "SECONDS", // DB2 //$NON-NLS-1$ "SECQTY", // DB2 //$NON-NLS-1$ "SECTION", //$NON-NLS-1$ "SECURITY", // DB2 //$NON-NLS-1$ "SELECT", // DB2 //$NON-NLS-1$ "SELF", //$NON-NLS-1$ "SENSITIVE", // DB2 //$NON-NLS-1$ "SEPARATOR", //$NON-NLS-1$ "SEQUENCE", //$NON-NLS-1$ "SERIALIZABLE", //$NON-NLS-1$ "SERVER_NAME", //$NON-NLS-1$ "SESSION", //$NON-NLS-1$ "SESSION_USER", //$NON-NLS-1$ "SET", // DB2 //$NON-NLS-1$ "SETOF", //$NON-NLS-1$ "SETS", //$NON-NLS-1$ "SETUSER", //$NON-NLS-1$ "SHARE", //$NON-NLS-1$ "SHOW", //$NON-NLS-1$ "SHUTDOWN", //$NON-NLS-1$ "SIGNAL", // DB2 //$NON-NLS-1$ "SIMILAR", //$NON-NLS-1$ "SIMPLE", // DB2 //$NON-NLS-1$ "SIZE", //$NON-NLS-1$ "SMALLINT", //$NON-NLS-1$ "SOME", // DB2 //$NON-NLS-1$ "SONAME", //$NON-NLS-1$ "SOURCE", // DB2 //$NON-NLS-1$ "SPACE", //$NON-NLS-1$ "SPATIAL", //$NON-NLS-1$ "SPECIFIC", // DB2 //$NON-NLS-1$ "SPECIFIC_NAME", //$NON-NLS-1$ "SPECIFICTYPE", //$NON-NLS-1$ "SQL", // DB2 //$NON-NLS-1$ "SQL_BIG_RESULT", //$NON-NLS-1$ "SQL_BIG_SELECTS", //$NON-NLS-1$ "SQL_BIG_TABLES", //$NON-NLS-1$ "SQL_CALC_FOUND_ROWS", //$NON-NLS-1$ "SQL_LOG_OFF", //$NON-NLS-1$ "SQL_LOG_UPDATE", //$NON-NLS-1$ "SQL_LOW_PRIORITY_UPDATES", //$NON-NLS-1$ "SQL_SELECT_LIMIT", //$NON-NLS-1$ "SQL_SMALL_RESULT", //$NON-NLS-1$ "SQL_WARNINGS", //$NON-NLS-1$ "SQLCA", //$NON-NLS-1$ "SQLCODE", //$NON-NLS-1$ "SQLERROR", //$NON-NLS-1$ "SQLEXCEPTION", //$NON-NLS-1$ "SQLID", // DB2 //$NON-NLS-1$ "SQLSTATE", //$NON-NLS-1$ "SQLWARNING", //$NON-NLS-1$ "SQRT", //$NON-NLS-1$ "SSL", //$NON-NLS-1$ "STABLE", //$NON-NLS-1$ "STANDARD", // DB2 //$NON-NLS-1$ "START", // DB2 //$NON-NLS-1$ "STARTING", //$NON-NLS-1$ "STATE", //$NON-NLS-1$ "STATEMENT", //$NON-NLS-1$ "STATIC", // DB2 //$NON-NLS-1$ "STATISTICS", //$NON-NLS-1$ "STATUS", //$NON-NLS-1$ "STAY", // DB2 //$NON-NLS-1$ "STDDEV_POP", //$NON-NLS-1$ "STDDEV_SAMP", //$NON-NLS-1$ "STDIN", //$NON-NLS-1$ "STDOUT", //$NON-NLS-1$ "STOGROUP", // DB2 //$NON-NLS-1$ "STORAGE", //$NON-NLS-1$ "STORES", // DB2 //$NON-NLS-1$ "STRAIGHT_JOIN", //$NON-NLS-1$ "STRICT", //$NON-NLS-1$ "STRING", //$NON-NLS-1$ "STRUCTURE", //$NON-NLS-1$ "STYLE", // DB2 //$NON-NLS-1$ "SUBCLASS_ORIGIN", //$NON-NLS-1$ "SUBLIST", //$NON-NLS-1$ "SUBMULTISET", //$NON-NLS-1$ "SUBPAGES", // DB2 //$NON-NLS-1$ "SUBSTRING", // DB2 //$NON-NLS-1$ "SUCCESSFUL", //$NON-NLS-1$ "SUM", //$NON-NLS-1$ "SUPERUSER", //$NON-NLS-1$ "SYMMETRIC", //$NON-NLS-1$ "SYNONYM", // DB2 //$NON-NLS-1$ "SYSDATE", //$NON-NLS-1$ "SYSFUN", // DB2 //$NON-NLS-1$ "SYSIBM", // DB2 //$NON-NLS-1$ "SYSID", //$NON-NLS-1$ "SYSPROC", // DB2 //$NON-NLS-1$ "SYSTEM", // DB2 //$NON-NLS-1$ "SYSTEM_USER", //$NON-NLS-1$ "TABLE", // DB2 //$NON-NLS-1$ "TABLE_NAME", //$NON-NLS-1$ "TABLES", //$NON-NLS-1$ "TABLESAMPLE", //$NON-NLS-1$ "TABLESPACE", // DB2 //$NON-NLS-1$ "TEMP", //$NON-NLS-1$ "TEMPLATE", //$NON-NLS-1$ "TEMPORARY", //$NON-NLS-1$ "TERMINATE", //$NON-NLS-1$ "TERMINATED", //$NON-NLS-1$ "TEXT", //$NON-NLS-1$ "TEXTSIZE", //$NON-NLS-1$ "THAN", //$NON-NLS-1$ "THEN", // DB2 //$NON-NLS-1$ "TIES", //$NON-NLS-1$ "TIME", //$NON-NLS-1$ "TIMESTAMP", //$NON-NLS-1$ "TIMEZONE_HOUR", //$NON-NLS-1$ "TIMEZONE_MINUTE", //$NON-NLS-1$ "TINYBLOB", //$NON-NLS-1$ "TINYINT", //$NON-NLS-1$ "TINYTEXT", //$NON-NLS-1$ "TO", // DB2 //$NON-NLS-1$ "TOAST", //$NON-NLS-1$ "TOP", //$NON-NLS-1$ "TOP_LEVEL_COUNT", //$NON-NLS-1$ "TRAILING", //$NON-NLS-1$ "TRAN", //$NON-NLS-1$ "TRANSACTION", // DB2 //$NON-NLS-1$ "TRANSACTION_ACTIVE", //$NON-NLS-1$ "TRANSACTIONS_COMMITTED", //$NON-NLS-1$ "TRANSACTIONS_ROLLED_BACK", //$NON-NLS-1$ "TRANSFORM", //$NON-NLS-1$ "TRANSFORMS", //$NON-NLS-1$ "TRANSLATE", //$NON-NLS-1$ "TRANSLATION", //$NON-NLS-1$ "TREAT", //$NON-NLS-1$ "TRIGGER", // DB2 //$NON-NLS-1$ "TRIGGER_CATALOG", //$NON-NLS-1$ "TRIGGER_NAME", //$NON-NLS-1$ "TRIGGER_SCHEMA", //$NON-NLS-1$ "TRIM", // DB2 //$NON-NLS-1$ "TRUE", //$NON-NLS-1$ "TRUNCATE", //$NON-NLS-1$ "TRUSTED", //$NON-NLS-1$ "TSEQUAL", //$NON-NLS-1$ "TYPE", // DB2 //$NON-NLS-1$ "UESCAPE", //$NON-NLS-1$ "UID", //$NON-NLS-1$ "UNBOUNDED", //$NON-NLS-1$ "UNCOMMITTED", //$NON-NLS-1$ "UNDER", //$NON-NLS-1$ "UNDO", // DB2 //$NON-NLS-1$ "UNENCRYPTED", //$NON-NLS-1$ "UNION", // DB2 //$NON-NLS-1$ "UNIQUE", // DB2 //$NON-NLS-1$ "UNKNOWN", //$NON-NLS-1$ "UNLISTEN", //$NON-NLS-1$ "UNLOCK", //$NON-NLS-1$ "UNNAMED", //$NON-NLS-1$ "UNNEST", //$NON-NLS-1$ "UNSIGNED", //$NON-NLS-1$ "UNTIL", // DB2 //$NON-NLS-1$ "UPDATE", // DB2 //$NON-NLS-1$ "UPDATETEXT", //$NON-NLS-1$ "UPPER", //$NON-NLS-1$ "USAGE", // DB2 //$NON-NLS-1$ "USE", //$NON-NLS-1$ "USER", // DB2 //$NON-NLS-1$ "USER_DEFINED_TYPE_CATALOG", //$NON-NLS-1$ "USER_DEFINED_TYPE_CODE", //$NON-NLS-1$ "USER_DEFINED_TYPE_NAME", //$NON-NLS-1$ "USER_DEFINED_TYPE_SCHEMA", //$NON-NLS-1$ "USING", // DB2 //$NON-NLS-1$ "UTC_DATE", //$NON-NLS-1$ "UTC_TIME", //$NON-NLS-1$ "UTC_TIMESTAMP", //$NON-NLS-1$ "VACUUM", //$NON-NLS-1$ "VALID", //$NON-NLS-1$ "VALIDATE", //$NON-NLS-1$ "VALIDATOR", //$NON-NLS-1$ "VALIDPROC", // DB2 //$NON-NLS-1$ "VALUE", //$NON-NLS-1$ "VALUES", // DB2 //$NON-NLS-1$ "VAR_POP", //$NON-NLS-1$ "VAR_SAMP", //$NON-NLS-1$ "VARBINARY", //$NON-NLS-1$ "VARCHAR", //$NON-NLS-1$ "VARCHAR2", //$NON-NLS-1$ "VARCHARACTER", //$NON-NLS-1$ "VARIABLE", // DB2 //$NON-NLS-1$ "VARIABLES", //$NON-NLS-1$ "VARIANT", // DB2 //$NON-NLS-1$ "VARYING", //$NON-NLS-1$ "VCAT", // DB2 //$NON-NLS-1$ "VERBOSE", //$NON-NLS-1$ "VIEW", // DB2 //$NON-NLS-1$ "VIRTUAL", //MySQL #272 "VOLATILE", //$NON-NLS-1$ "VOLUMES", // DB2 //$NON-NLS-1$ "WAITFOR", //$NON-NLS-1$ "WHEN", // DB2 //$NON-NLS-1$ "WHENEVER", //$NON-NLS-1$ "WHERE", // DB2 //$NON-NLS-1$ "WHILE", // DB2 //$NON-NLS-1$ "WIDTH_BUCKET", //$NON-NLS-1$ "WINDOW", //$NON-NLS-1$ "WITH", // DB2 //$NON-NLS-1$ "WITHIN", //$NON-NLS-1$ "WITHOUT", //$NON-NLS-1$ "WLM", // DB2 //$NON-NLS-1$ "WORK", //$NON-NLS-1$ "WRITE", // DB2 //$NON-NLS-1$ "WRITETEXT", //$NON-NLS-1$ "X509", //$NON-NLS-1$ "XOR", //$NON-NLS-1$ "YEAR", // DB2 //$NON-NLS-1$ "YEAR_MONTH", //$NON-NLS-1$ "YEARS", // DB2 //$NON-NLS-1$ "ZEROFILL", //$NON-NLS-1$ "ZONE" //$NON-NLS-1$ }; RESERVED_WORDS = new HashSet(words.length); for (String word : words) { RESERVED_WORDS.add(word); } } /** * Utility class - no instances allowed. */ private SqlReservedWords() { } public static boolean containsWord(String word) { boolean rc; if (word == null) { rc = false; } else { rc = RESERVED_WORDS.contains(word.toUpperCase()); } return rc; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/Sqls.java ================================================ package tk.mybatis.mapper.util; import java.util.ArrayList; import java.util.List; /** * @author wuyi * @date 2017/11/18 */ public class Sqls { private Criteria criteria; private Sqls() { this.criteria = new Criteria(); } public static Sqls custom() { return new Sqls(); } public Criteria getCriteria() { return criteria; } public Sqls andIsNull(String property) { this.criteria.criterions.add(new Criterion(property, "is null", "and")); return this; } public Sqls andIsNotNull(String property) { this.criteria.criterions.add(new Criterion(property, "is not null", "and")); return this; } public Sqls andEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "=", "and")); return this; } public Sqls andNotEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "<>", "and")); return this; } public Sqls andGreaterThan(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, ">", "and")); return this; } public Sqls andGreaterThanOrEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, ">=", "and")); return this; } public Sqls andLessThan(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "<", "and")); return this; } public Sqls andLessThanOrEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "<=", "and")); return this; } public Sqls andIn(String property, Iterable values) { this.criteria.criterions.add(new Criterion(property, values, "in", "and")); return this; } public Sqls andNotIn(String property, Iterable values) { this.criteria.criterions.add(new Criterion(property, values, "not in", "and")); return this; } public Sqls andBetween(String property, Object value1, Object value2) { this.criteria.criterions.add(new Criterion(property, value1, value2, "between", "and")); return this; } public Sqls andNotBetween(String property, Object value1, Object value2) { this.criteria.criterions.add(new Criterion(property, value1, value2, "not between", "and")); return this; } public Sqls andLike(String property, String value) { this.criteria.criterions.add(new Criterion(property, value, "like", "and")); return this; } public Sqls andNotLike(String property, String value) { this.criteria.criterions.add(new Criterion(property, value, "not like", "and")); return this; } public Sqls orIsNull(String property) { this.criteria.criterions.add(new Criterion(property, "is null", "or")); return this; } public Sqls orIsNotNull(String property) { this.criteria.criterions.add(new Criterion(property, "is not null", "or")); return this; } public Sqls orEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "=", "or")); return this; } public Sqls orNotEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "<>", "or")); return this; } public Sqls orGreaterThan(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, ">", "or")); return this; } public Sqls orGreaterThanOrEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, ">=", "or")); return this; } public Sqls orLessThan(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "<", "or")); return this; } public Sqls orLessThanOrEqualTo(String property, Object value) { this.criteria.criterions.add(new Criterion(property, value, "<=", "or")); return this; } public Sqls orIn(String property, Iterable values) { this.criteria.criterions.add(new Criterion(property, values, "in", "or")); return this; } public Sqls orNotIn(String property, Iterable values) { this.criteria.criterions.add(new Criterion(property, values, "not in", "or")); return this; } public Sqls orBetween(String property, Object value1, Object value2) { this.criteria.criterions.add(new Criterion(property, value1, value2, "between", "or")); return this; } public Sqls orNotBetween(String property, Object value1, Object value2) { this.criteria.criterions.add(new Criterion(property, value1, value2, "not between", "or")); return this; } public Sqls orLike(String property, String value) { this.criteria.criterions.add(new Criterion(property, value, "like", "or")); return this; } public Sqls orNotLike(String property, String value) { this.criteria.criterions.add(new Criterion(property, value, "not like", "or")); return this; } public static class Criteria { private String andOr; private List criterions; public Criteria() { this.criterions = new ArrayList(2); } public List getCriterions() { return criterions; } public String getAndOr() { return andOr; } public void setAndOr(String andOr) { this.andOr = andOr; } } public static class Criterion { private String property; private Object value; private Object secondValue; private String condition; private String andOr; public Criterion(String property, String condition, String andOr) { this.property = property; this.condition = condition; this.andOr = andOr; } public Criterion(String property, Object value, String condition, String andOr) { this.property = property; this.value = value; this.condition = condition; this.andOr = andOr; } public Criterion(String property, Object value1, Object value2, String condition, String andOr) { this.property = property; this.value = value1; this.secondValue = value2; this.condition = condition; this.andOr = andOr; } public String getProperty() { return property; } public Object getValue() { return value; } public Object getSecondValue() { return secondValue; } public Object[] getValues() { if (value != null) { if (secondValue != null) { return new Object[]{value, secondValue}; } else { return new Object[]{value}; } } else { return new Object[]{}; } } public String getCondition() { return condition; } public String getAndOr() { return andOr; } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/util/StringUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import tk.mybatis.mapper.code.Style; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by liuzh_3nofxnp on 2015/8/26. */ public class StringUtil { private static Pattern UNDERLINE_TO_CAMELHUMP_PATTERN = Pattern.compile("_[a-z]"); /** * 空 * * @param str * @return */ public static boolean isEmpty(String str) { return str == null || str.length() == 0; } /** * 非空 * * @param str * @return */ public static boolean isNotEmpty(String str) { return !isEmpty(str); } /** * 根据指定的样式进行转换 * * @param str * @param style * @return */ public static String convertByStyle(String str, Style style) { switch (style) { case camelhump: return camelhumpToUnderline(str); case uppercase: return str.toUpperCase(); case lowercase: return str.toLowerCase(); case camelhumpAndLowercase: return camelhumpToUnderline(str).toLowerCase(); case camelhumpAndUppercase: return camelhumpToUnderline(str).toUpperCase(); case normal: default: return str; } } /** * 将驼峰风格替换为下划线风格 */ public static String camelhumpToUnderline(String str) { final int size; final char[] chars; final StringBuilder sb = new StringBuilder( (size = (chars = str.toCharArray()).length) * 3 / 2 + 1); char c; for (int i = 0; i < size; i++) { c = chars[i]; if (isUppercaseAlpha(c)) { sb.append('_').append(toLowerAscii(c)); } else { sb.append(c); } } return sb.charAt(0) == '_' ? sb.substring(1) : sb.toString(); } /** * 将下划线风格替换为驼峰风格 */ public static String underlineToCamelhump(String str) { Matcher matcher = UNDERLINE_TO_CAMELHUMP_PATTERN.matcher(str); StringBuilder builder = new StringBuilder(str); for (int i = 0; matcher.find(); i++) { builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase()); } if (Character.isUpperCase(builder.charAt(0))) { builder.replace(0, 1, String.valueOf(Character.toLowerCase(builder.charAt(0)))); } return builder.toString(); } public static boolean isUppercaseAlpha(char c) { return (c >= 'A') && (c <= 'Z'); } public static boolean isLowercaseAlpha(char c) { return (c >= 'a') && (c <= 'z'); } public static char toUpperAscii(char c) { if (isLowercaseAlpha(c)) { c -= (char) 0x20; } return c; } public static char toLowerAscii(char c) { if (isUppercaseAlpha(c)) { c += (char) 0x20; } return c; } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/version/DefaultNextVersion.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.version; import java.sql.Timestamp; /** * @author liuzh * @since 3.5.0 */ public class DefaultNextVersion implements NextVersion { @Override public Object nextVersion(Object current) throws VersionException { if (current == null) { throw new VersionException("当前版本号为空!"); } if (current instanceof Integer) { return (Integer) current + 1; } else if (current instanceof Long) { return (Long) current + 1L; } else if (current instanceof Timestamp) { return new Timestamp(System.currentTimeMillis()); } else { throw new VersionException("默认的 NextVersion 只支持 Integer, Long 和 java.sql.Timestamp 类型的版本号,如果有需要请自行扩展!"); } } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/version/NextVersion.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.version; /** * @author liuzh * @since 3.5.0 */ public interface NextVersion { /** * 返回下一个版本 * * @param current * @return */ T nextVersion(T current) throws VersionException; } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/version/VersionException.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.version; /** * @author liuzh * @since 3.5.0 */ public class VersionException extends RuntimeException { public VersionException() { super(); } public VersionException(String message) { super(message); } public VersionException(String message, Throwable cause) { super(message, cause); } public VersionException(Throwable cause) { super(cause); } } ================================================ FILE: core/src/main/java/tk/mybatis/mapper/version/VersionUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.version; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; /** * @author liuzh * @since 3.5.0 */ public class VersionUtil { private static final Map, NextVersion> CACHE = new ConcurrentHashMap, NextVersion>(); private static final ReentrantLock LOCK = new ReentrantLock(); /** * 获取下一个版本 * * @param nextVersionClass * @param current * @return * @throws VersionException */ public static Object nextVersion(Class nextVersionClass, Object current) throws VersionException { try { NextVersion nextVersion; if (CACHE.containsKey(nextVersionClass)) { nextVersion = CACHE.get(nextVersionClass); } else { LOCK.lock(); try { if (!CACHE.containsKey(nextVersionClass)) { CACHE.put(nextVersionClass, nextVersionClass.newInstance()); } nextVersion = CACHE.get(nextVersionClass); } finally { LOCK.unlock(); } } return nextVersion.nextVersion(current); } catch (Exception e) { throw new VersionException("获取下一个版本号失败!", e); } } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/ColumnTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.StringTypeHandler; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import jakarta.persistence.Column; import java.util.Set; /** * @author liuzh */ public class ColumnTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } class UserColumn { @Column(name = "user_name") private String name; } @Test public void testColumn() { EntityHelper.initEntityNameMap(UserColumn.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserColumn.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("user_name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("user_name = #{name}", column.getColumnEqualsHolder()); Assert.assertEquals("user_name = #{record.name}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name}", column.getColumnHolder()); Assert.assertEquals("#{record.name}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USER_NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("user_name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/ColumnTypeTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.BlobTypeHandler; import org.apache.ibatis.type.EnumOrdinalTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.StringTypeHandler; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import java.util.Set; /** * @author liuzh */ public class ColumnTypeTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } class UserColumn { @ColumnType(column = "user_name") private String name; } @Test public void testColumn() { EntityHelper.initEntityNameMap(UserColumn.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserColumn.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("user_name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("user_name = #{name}", column.getColumnEqualsHolder()); Assert.assertEquals("user_name = #{record.name}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name}", column.getColumnHolder()); Assert.assertEquals("#{record.name}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USER_NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("user_name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } class UserJdbcTypeVarchar { @ColumnType(jdbcType = JdbcType.VARCHAR) private String name; } @Test public void testJdbcTypeVarchar() { EntityHelper.initEntityNameMap(UserJdbcTypeVarchar.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserJdbcTypeVarchar.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("name = #{name, jdbcType=VARCHAR}", column.getColumnEqualsHolder()); Assert.assertEquals("name = #{record.name, jdbcType=VARCHAR}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name, jdbcType=VARCHAR}", column.getColumnHolder()); Assert.assertEquals("#{record.name, jdbcType=VARCHAR}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name, jdbcType=VARCHAR}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix, jdbcType=VARCHAR},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNotNull(resultMapping.getJdbcType()); Assert.assertEquals(JdbcType.VARCHAR, resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } class UserJdbcTypeBlob { @ColumnType(jdbcType = JdbcType.BLOB) private String name; } @Test public void testJdbcTypeBlob() { EntityHelper.initEntityNameMap(UserJdbcTypeBlob.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserJdbcTypeBlob.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("name = #{name, jdbcType=BLOB}", column.getColumnEqualsHolder()); Assert.assertEquals("name = #{record.name, jdbcType=BLOB}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name, jdbcType=BLOB}", column.getColumnHolder()); Assert.assertEquals("#{record.name, jdbcType=BLOB}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name, jdbcType=BLOB}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix, jdbcType=BLOB},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNotNull(resultMapping.getJdbcType()); Assert.assertEquals(JdbcType.BLOB, resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } class UserTypehandler { @ColumnType(typeHandler = BlobTypeHandler.class) private String name; } @Test public void testTypehandler() { EntityHelper.initEntityNameMap(UserTypehandler.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserTypehandler.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("name = #{name, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnEqualsHolder()); Assert.assertEquals("name = #{record.name, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnHolder()); Assert.assertEquals("#{record.name, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix, typeHandler=org.apache.ibatis.type.BlobTypeHandler},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNotNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(BlobTypeHandler.class, resultMapping.getTypeHandler().getClass()); } enum UserEnum { A, B } class UserEnumOrdinalTypeHandler { @ColumnType(typeHandler = EnumOrdinalTypeHandler.class) private UserEnum name; } @Test public void testEnumOrdinalTypeHandler() { EntityHelper.initEntityNameMap(UserEnumOrdinalTypeHandler.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserEnumOrdinalTypeHandler.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("name = #{name, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}", column.getColumnEqualsHolder()); Assert.assertEquals("name = #{record.name, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}", column.getColumnHolder()); Assert.assertEquals("#{record.name, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNotNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(EnumOrdinalTypeHandler.class, resultMapping.getTypeHandler().getClass()); } class UserAll { @ColumnType(column = "user_name", jdbcType = JdbcType.BLOB, typeHandler = BlobTypeHandler.class) private String name; } @Test public void testAll() { EntityHelper.initEntityNameMap(UserAll.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserAll.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("user_name", column.getColumn()); Assert.assertEquals("name", column.getProperty()); Assert.assertEquals("user_name = #{name, jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnEqualsHolder()); Assert.assertEquals("user_name = #{record.name, jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{name, jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnHolder()); Assert.assertEquals("#{record.name, jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnHolder("record")); Assert.assertEquals("#{record.name, jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.namesuffix, jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNotNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USER_NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("user_name", resultMapping.getColumn()); Assert.assertEquals("name", resultMapping.getProperty()); Assert.assertNotNull(resultMapping.getJdbcType()); Assert.assertEquals(BlobTypeHandler.class, resultMapping.getTypeHandler().getClass()); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/IdTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.mapping.ResultFlag; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.session.Configuration; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.SqlHelper; import jakarta.persistence.Id; import java.util.Set; /** * @author liuzh */ public class IdTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } class UserSingleId { @Id private String name; } @Test public void testSingleId() { EntityHelper.initEntityNameMap(UserSingleId.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserSingleId.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertTrue(column.isId()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals(1, resultMap.getResultMappings().size()); Assert.assertTrue(resultMap.getResultMappings().get(0).getFlags().contains(ResultFlag.ID)); Assert.assertEquals(" AND name = #{name}", SqlHelper.wherePKColumns(UserSingleId.class)); } class UserCompositeKeys { @Id private String name; @Id private String orgId; } @Test public void testCompositeKeys() { EntityHelper.initEntityNameMap(UserCompositeKeys.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserCompositeKeys.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(2, columns.size()); Assert.assertEquals(2, entityTable.getEntityClassPKColumns().size()); for (EntityColumn column : columns) { Assert.assertTrue(column.isId()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals(2, resultMap.getResultMappings().size()); Assert.assertTrue(resultMap.getResultMappings().get(0).getFlags().contains(ResultFlag.ID)); Assert.assertTrue(resultMap.getResultMappings().get(1).getFlags().contains(ResultFlag.ID)); Assert.assertEquals(" AND name = #{name} AND orgId = #{orgId}", SqlHelper.wherePKColumns(UserCompositeKeys.class)); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/KeySqlTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.session.Configuration; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.IdentityDialect; import tk.mybatis.mapper.code.ORDER; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import java.util.Set; /** * @author liuzh */ public class KeySqlTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } class UserJDBC { @KeySql(useGeneratedKeys = true) private Long id; } @Test public void testUseGeneratedKeys() { EntityHelper.initEntityNameMap(UserJDBC.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserJDBC.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("JDBC", column.getGenerator()); Assert.assertTrue(column.isIdentity()); } } class UserDialect { @KeySql(dialect = IdentityDialect.MYSQL) private Long id; } @Test public void testDialect() { EntityHelper.initEntityNameMap(UserDialect.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserDialect.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("SELECT LAST_INSERT_ID()", column.getGenerator()); Assert.assertEquals(ORDER.AFTER, column.getOrder()); Assert.assertTrue(column.isIdentity()); } } class UserSql { @KeySql(sql = "select seq.nextval from dual", order = ORDER.BEFORE) private Long id; } @Test public void testSql() { EntityHelper.initEntityNameMap(UserSql.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserSql.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("select seq.nextval from dual", column.getGenerator()); Assert.assertEquals(ORDER.BEFORE, column.getOrder()); Assert.assertTrue(column.isIdentity()); } } class UserAll { @KeySql(useGeneratedKeys = true, dialect = IdentityDialect.MYSQL, sql = "select 1", order = ORDER.BEFORE) private Long id; } @Test public void testAll() { EntityHelper.initEntityNameMap(UserAll.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserAll.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("JDBC", column.getGenerator()); Assert.assertTrue(column.isIdentity()); } } class UserAll2 { @KeySql(dialect = IdentityDialect.MYSQL, sql = "select 1", order = ORDER.BEFORE) private Long id; } @Test public void testAll2() { EntityHelper.initEntityNameMap(UserAll2.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserAll2.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("SELECT LAST_INSERT_ID()", column.getGenerator()); Assert.assertEquals(ORDER.AFTER, column.getOrder()); Assert.assertTrue(column.isIdentity()); } } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/NameStyleTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.StringTypeHandler; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import java.util.Set; /** * @author liuzh */ public class NameStyleTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } @NameStyle(Style.camelhump) class UserCamelhump { private String userName; } @Test public void testCamelhump() { EntityHelper.initEntityNameMap(UserCamelhump.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserCamelhump.class); Assert.assertNotNull(entityTable); Assert.assertEquals("user_camelhump", entityTable.getName()); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("user_name", column.getColumn()); Assert.assertEquals("userName", column.getProperty()); Assert.assertEquals("user_name = #{userName}", column.getColumnEqualsHolder()); Assert.assertEquals("user_name = #{record.userName}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{userName}", column.getColumnHolder()); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record")); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.userNamesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USER_NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("user_name", resultMapping.getColumn()); Assert.assertEquals("userName", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } @NameStyle(Style.camelhumpAndUppercase) class UserCamelhumpAndUppercase { private String userName; } @Test public void testCamelhumpAndUppercase() { EntityHelper.initEntityNameMap(UserCamelhumpAndUppercase.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserCamelhumpAndUppercase.class); Assert.assertNotNull(entityTable); Assert.assertEquals("USER_CAMELHUMP_AND_UPPERCASE", entityTable.getName()); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("USER_NAME", column.getColumn()); Assert.assertEquals("userName", column.getProperty()); Assert.assertEquals("USER_NAME = #{userName}", column.getColumnEqualsHolder()); Assert.assertEquals("USER_NAME = #{record.userName}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{userName}", column.getColumnHolder()); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record")); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.userNamesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USER_NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("USER_NAME", resultMapping.getColumn()); Assert.assertEquals("userName", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } @NameStyle(Style.camelhumpAndLowercase) class UserCamelhumpAndLowercase { private String userName; } @Test public void testCamelhumpAndLowercase() { EntityHelper.initEntityNameMap(UserCamelhumpAndLowercase.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserCamelhumpAndLowercase.class); Assert.assertNotNull(entityTable); Assert.assertEquals("user_camelhump_and_lowercase", entityTable.getName()); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("user_name", column.getColumn()); Assert.assertEquals("userName", column.getProperty()); Assert.assertEquals("user_name = #{userName}", column.getColumnEqualsHolder()); Assert.assertEquals("user_name = #{record.userName}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{userName}", column.getColumnHolder()); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record")); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.userNamesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USER_NAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("user_name", resultMapping.getColumn()); Assert.assertEquals("userName", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } @NameStyle(Style.normal) class UserNormal { private String userName; } @Test public void testNormal() { EntityHelper.initEntityNameMap(UserNormal.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserNormal.class); Assert.assertNotNull(entityTable); Assert.assertEquals("UserNormal", entityTable.getName()); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("userName", column.getColumn()); Assert.assertEquals("userName", column.getProperty()); Assert.assertEquals("userName = #{userName}", column.getColumnEqualsHolder()); Assert.assertEquals("userName = #{record.userName}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{userName}", column.getColumnHolder()); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record")); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.userNamesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USERNAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("userName", resultMapping.getColumn()); Assert.assertEquals("userName", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } @NameStyle(Style.uppercase) class UserUppercase { private String userName; } @Test public void testUppercase() { EntityHelper.initEntityNameMap(UserUppercase.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserUppercase.class); Assert.assertNotNull(entityTable); Assert.assertEquals("USERUPPERCASE", entityTable.getName()); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("USERNAME", column.getColumn()); Assert.assertEquals("userName", column.getProperty()); Assert.assertEquals("USERNAME = #{userName}", column.getColumnEqualsHolder()); Assert.assertEquals("USERNAME = #{record.userName}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{userName}", column.getColumnHolder()); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record")); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.userNamesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USERNAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("USERNAME", resultMapping.getColumn()); Assert.assertEquals("userName", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } @NameStyle(Style.lowercase) class UserLowercase { private String userName; } @Test public void testLowercase() { EntityHelper.initEntityNameMap(UserLowercase.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserLowercase.class); Assert.assertNotNull(entityTable); Assert.assertEquals("userlowercase", entityTable.getName()); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertEquals("username", column.getColumn()); Assert.assertEquals("userName", column.getProperty()); Assert.assertEquals("username = #{userName}", column.getColumnEqualsHolder()); Assert.assertEquals("username = #{record.userName}", column.getColumnEqualsHolder("record")); Assert.assertEquals("#{userName}", column.getColumnHolder()); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record")); Assert.assertEquals("#{record.userName}", column.getColumnHolder("record", "suffix")); Assert.assertEquals("#{record.userNamesuffix},", column.getColumnHolder("record", "suffix", ",")); Assert.assertNull(column.getTypeHandler()); } ResultMap resultMap = entityTable.getResultMap(configuration); Assert.assertEquals("[USERNAME]", resultMap.getMappedColumns().toString()); Assert.assertEquals(1, resultMap.getResultMappings().size()); ResultMapping resultMapping = resultMap.getResultMappings().get(0); Assert.assertEquals("username", resultMapping.getColumn()); Assert.assertEquals("userName", resultMapping.getProperty()); Assert.assertNull(resultMapping.getJdbcType()); Assert.assertEquals(StringTypeHandler.class, resultMapping.getTypeHandler().getClass()); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/RegisterMapperTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.session.Configuration; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; /** * @author liuzh */ public class RegisterMapperTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } @RegisterMapper interface MapperHashRegisterMapper { } interface UserMapper extends MapperHashRegisterMapper { } @Test public void testHashRegisterMapper() { MapperHelper mapperHelper = new MapperHelper(); Assert.assertTrue(mapperHelper.isExtendCommonMapper(UserMapper.class)); } interface RoleMapper { } @Test public void testRoleMapper() { MapperHelper mapperHelper = new MapperHelper(); Assert.assertFalse(mapperHelper.isExtendCommonMapper(RoleMapper.class)); } @RegisterMapper interface RoleMapper2 { } @Test public void testRoleMapper2() { MapperHelper mapperHelper = new MapperHelper(); Assert.assertFalse(mapperHelper.isExtendCommonMapper(RoleMapper2.class)); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/TableTest.java ================================================ package tk.mybatis.mapper.annotation; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import jakarta.persistence.Table; /** * @author liuzh */ public class TableTest { private Config config; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); } @Table(name = "sys_user") class User { private String name; } @Test public void testColumn() { EntityHelper.initEntityNameMap(User.class, config); EntityTable entityTable = EntityHelper.getEntityTable(User.class); Assert.assertNotNull(entityTable); Assert.assertEquals("sys_user", entityTable.getName()); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/annotation/VersionTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.session.Configuration; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.version.VersionException; import java.util.Set; /** * @author liuzh */ public class VersionTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); configuration = new Configuration(); } class UserVersion { @Version private String name; } @Test public void testVersion() { EntityHelper.initEntityNameMap(UserVersion.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserVersion.class); Assert.assertNotNull(entityTable); Set columns = entityTable.getEntityClassColumns(); Assert.assertEquals(1, columns.size()); for (EntityColumn column : columns) { Assert.assertTrue(column.getEntityField().isAnnotationPresent(Version.class)); } } /** * 一个实体类中只能有一个 @Version 注解 */ class UserVersionError { @Version private Long id; @Version private String name; } @Test(expected = VersionException.class) public void testVersionError() { EntityHelper.initEntityNameMap(UserVersionError.class, config); EntityTable entityTable = EntityHelper.getEntityTable(UserVersionError.class); Assert.assertNotNull(entityTable); SqlHelper.wherePKColumns(UserVersionError.class, true); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/mapperhelper/ComplexEntityTest.java ================================================ package tk.mybatis.mapper.mapperhelper; import org.apache.ibatis.mapping.ResultFlag; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.EnumTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.annotation.ColumnType; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityTable; import jakarta.persistence.Column; import jakarta.persistence.Id; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; /** * @author liuzh */ public class ComplexEntityTest { private Config config; private Configuration configuration; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.camelhump); configuration = new Configuration(); } static class Address { private String street; private String zipCode; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getZipCode() { return zipCode; } public void setZipCode(String zipCode) { this.zipCode = zipCode; } } static enum State { ENABLE, DISABLE } public static class AddressHandler implements TypeHandler

{ public AddressHandler() { System.out.println("init"); } @Override public void setParameter(PreparedStatement ps, int i, Address parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.getStreet()); } @Override public Address getResult(ResultSet rs, String columnName) throws SQLException { final String value = rs.getString(columnName); final Address address = new Address(); address.setStreet(value); return address; } @Override public Address getResult(ResultSet rs, int columnIndex) throws SQLException { final String value = rs.getString(columnIndex); final Address address = new Address(); address.setStreet(value); return address; } @Override public Address getResult(CallableStatement cs, int columnIndex) throws SQLException { return null; } } static class User { @Id private Long id; private String userName; @Column @ColumnType(typeHandler = AddressHandler.class) private Address address; @Column private State state; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public State getState() { return state; } public void setState(State state) { this.state = state; } } @Test public void test() { Class entityClass = User.class; EntityHelper.initEntityNameMap(entityClass, config); StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.append(SqlHelper.selectAllColumns(entityClass)); final EntityTable entityTable = EntityHelper.getEntityTable(entityClass); sqlBuilder.append(SqlHelper.fromTable(entityClass, entityTable.getName())); sqlBuilder.append(SqlHelper.whereAllIfColumns(entityClass, config.isNotEmpty())); final String sql = sqlBuilder.toString(); Assert.assertEquals("SELECT address,id,state,user_name FROM user " + "" + " AND address = #{address, typeHandler=tk.mybatis.mapper.mapperhelper.ComplexEntityTest$AddressHandler}" + " AND id = #{id}" + " AND state = #{state}" + " AND user_name = #{userName}", sql); final ResultMap resultMap = entityTable.getResultMap(configuration); final List resultMappings = resultMap.getResultMappings(); final ResultMapping addressMapping = resultMappings.get(0); final ResultMapping idMapping = resultMappings.get(1); final ResultMapping stateMapping = resultMappings.get(2); final ResultMapping userNameMapping = resultMappings.get(3); Assert.assertEquals("id", idMapping.getColumn()); Assert.assertEquals("id", idMapping.getProperty()); Assert.assertTrue(idMapping.getFlags().contains(ResultFlag.ID)); Assert.assertEquals("user_name", userNameMapping.getColumn()); Assert.assertEquals("userName", userNameMapping.getProperty()); Assert.assertEquals("address", addressMapping.getColumn()); Assert.assertEquals("address", addressMapping.getProperty()); Assert.assertEquals(AddressHandler.class, addressMapping.getTypeHandler().getClass()); Assert.assertEquals("state", stateMapping.getColumn()); Assert.assertEquals("state", stateMapping.getProperty()); Assert.assertEquals(EnumTypeHandler.class, stateMapping.getTypeHandler().getClass()); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/mapperhelper/FieldHelperTest.java ================================================ package tk.mybatis.mapper.mapperhelper; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.EntityField; import java.util.List; /** * @author liuzh */ public class FieldHelperTest { static class User { private Integer id; private String name; private transient String other1; public static final Integer FINAL = 1; } @Test public void testUser() { List fieldList = FieldHelper.getFields(User.class); Assert.assertEquals(2, fieldList.size()); Assert.assertEquals("id", fieldList.get(0).getName()); Assert.assertEquals("name", fieldList.get(1).getName()); } static class Admin { private Integer admin; private User user; } @Test public void testComplex() { List fieldList = FieldHelper.getFields(Admin.class); Assert.assertEquals(2, fieldList.size()); Assert.assertEquals("admin", fieldList.get(0).getName()); Assert.assertEquals("user", fieldList.get(1).getName()); } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/mapperhelper/SqlHelperTest.java ================================================ package tk.mybatis.mapper.mapperhelper; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import tk.mybatis.mapper.annotation.LogicDelete; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import jakarta.persistence.*; public class SqlHelperTest { private Config config; @Before public void beforeTest() { config = new Config(); config.setStyle(Style.normal); EntityHelper.initEntityNameMap(User.class, config); } @Test public void testLogicDeleteSql() { String wherePKColumns = SqlHelper.wherePKColumns(User.class); Assert.assertEquals(" AND id = #{id} AND is_valid = 1", wherePKColumns); String whereAllIfColumns = SqlHelper.whereAllIfColumns(User.class, false); Assert.assertEquals(" AND id = #{id} AND username = #{username} AND is_valid = 1", whereAllIfColumns); String isLogicDeletedColumn = SqlHelper.whereLogicDelete(User.class, true); Assert.assertEquals(" AND is_valid = 0", isLogicDeletedColumn); String notLogicDeletedColumn = SqlHelper.whereLogicDelete(User.class, false); Assert.assertEquals(" AND is_valid = 1", notLogicDeletedColumn); String updateSetColumns = SqlHelper.updateSetColumns(User.class, null, false, false); Assert.assertEquals("is_valid = 1,username = #{username},", updateSetColumns); } } @Table(name = "tb_user") class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "username") private String username; @LogicDelete(isDeletedValue = 0, notDeletedValue = 1) @Column(name = "is_valid") private Integer isValid; @Override public String toString() { return "TbUser{" + "id=" + id + ", username='" + username + '\'' + ", isValid=" + isValid + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getIsValid() { return isValid; } public void setIsValid(Integer isValid) { this.isValid = isValid; } } ================================================ FILE: core/src/test/java/tk/mybatis/mapper/util/StringUtilTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2019 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.util; import org.junit.Test; import org.junit.Assert; import tk.mybatis.mapper.code.Style; public class StringUtilTest { @Test public void testIsEmpty() { Assert.assertTrue(StringUtil.isEmpty(null)); Assert.assertTrue(StringUtil.isEmpty("")); Assert.assertFalse(StringUtil.isEmpty(" ")); Assert.assertFalse(StringUtil.isEmpty("foo")); } @Test public void testIsNotEmpty() { Assert.assertFalse(StringUtil.isNotEmpty(null)); Assert.assertFalse(StringUtil.isNotEmpty("")); Assert.assertTrue(StringUtil.isNotEmpty(" ")); Assert.assertTrue(StringUtil.isNotEmpty("foo")); } @Test public void testConvertByStyle() { Assert.assertEquals("fOo", StringUtil.convertByStyle("fOo", Style.normal)); Assert.assertEquals("f_oo", StringUtil.convertByStyle("fOo", Style.camelhump)); Assert.assertEquals("FOO", StringUtil.convertByStyle("fOo", Style.uppercase)); Assert.assertEquals("foo", StringUtil.convertByStyle("FoO", Style.lowercase)); Assert.assertEquals("fo_o", StringUtil.convertByStyle("FoO", Style.camelhumpAndLowercase)); Assert.assertEquals("F_OO", StringUtil.convertByStyle("fOo", Style.camelhumpAndUppercase)); } @Test public void testCamelhumpToUnderline() { Assert.assertEquals("foo", StringUtil.camelhumpToUnderline("foo")); Assert.assertEquals("f_oo", StringUtil.camelhumpToUnderline("fOo")); } @Test public void testUnderlineToCamelhump() { Assert.assertEquals("foo", StringUtil.underlineToCamelhump("foo")); Assert.assertEquals("foo", StringUtil.underlineToCamelhump("Foo")); } @Test public void testIsUppercaseAlpha() { Assert.assertTrue(StringUtil.isUppercaseAlpha('F')); Assert.assertFalse(StringUtil.isUppercaseAlpha('f')); } @Test public void testIsLowercaseAlpha() { Assert.assertTrue(StringUtil.isLowercaseAlpha('f')); Assert.assertFalse(StringUtil.isLowercaseAlpha('F')); } @Test public void testToUpperAscii() { Assert.assertEquals('F', StringUtil.toUpperAscii('f')); Assert.assertEquals('F', StringUtil.toUpperAscii('F')); } @Test public void testToLowerAscii() { Assert.assertEquals('f', StringUtil.toLowerAscii('f')); Assert.assertEquals('f', StringUtil.toLowerAscii('F')); } } ================================================ FILE: extra/README.md ================================================ # Mybatis 通用 Mapper 扩展方法 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-extra/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-extra) ## 扩展方法介绍 ### InsertListMapper 批量插入 - 支持批量插入的数据库都可以使用,例如 mysql,h2 等 `tk.mybatis.mapper.additional.insert.InsertListMapper` SQL 形如 `insert table(xxx) values (xxx), (xxx) ...` - Oracle特殊批量插入 `tk.mybatis.mapper.additional.dialect.oracle.InsertListMapper` SQL 形如 ```sql INSERT ALL INTO demo_country ( country_id,country_name,country_code ) VALUES ( ?,?,? ) INTO demo_country ( country_id,country_name,country_code ) VALUES ( ?,?,? ) INTO demo_country ( country_id,country_name,country_code ) VALUES ( ?,?,? ) SELECT 1 FROM DUAL ``` **由于语法限制,暂不支持序列.** ### UpdateByPrimaryKeySelectiveForceMapper 空字段强制更新 针对`UpdateByPrimaryKeySelectiveMapper`中, 空值也需要设置的场景提供的解决方案。 参见: [https://github.com/abel533/Mapper/issues/133](https://github.com/abel533/Mapper/issues/133) ================================================ FILE: extra/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-extra jar mapper-extra Mybatis 通用 Mapper 扩展方法 org.mybatis mybatis tk.mybatis mapper-core ${project.version} provided tk.mybatis mapper-weekend ${project.version} provided tk.mybatis mapper-base ${project.version} test ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/aggregation/AggregateCondition.java ================================================ package tk.mybatis.mapper.additional.aggregation; import tk.mybatis.mapper.util.Assert; import tk.mybatis.mapper.util.StringUtil; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 聚合查询条件 * * @author liuchan * @author liuzh */ public class AggregateCondition implements Serializable { private static final long serialVersionUID = 1L; // 聚合属性 private String aggregateProperty; private String aggregateAliasName; // groupBy 查询列 private List groupByProperties; // 聚合函数 private AggregateType aggregateType; public AggregateCondition() { this(null, AggregateType.COUNT, null); } /** * 默认查询count计数,不分组 * * @param aggregateProperty 聚合查询属性,不能为空;为保证返回结果key与传入值相同 方法不会去除前后空格 */ public AggregateCondition(String aggregateProperty) { this(aggregateProperty, AggregateType.COUNT, null); } /** * 默认查询count计数 * * @param aggregateProperty 聚合查询属性,不能为空;为保证返回结果key与传入值相同 方法不会去除前后空格 * @param groupByProperties 为保证返回结果key与传入值相同 方法不会去除每一项前后空格 */ public AggregateCondition(String aggregateProperty, String[] groupByProperties) { this(aggregateProperty, AggregateType.COUNT, groupByProperties); } /** * 按指定聚合方法查询,不分组 * * @param aggregateProperty * @param aggregateType */ public AggregateCondition(String aggregateProperty, AggregateType aggregateType) { this(aggregateProperty, aggregateType, null); } /** * @param aggregateProperty 不能为空,为保证返回结果key与传入值相同 方法不会去除前后空格 * @param aggregateType * @param groupByProperties 为保证返回结果key与传入值相同 方法不会去除每一项前后空格 */ public AggregateCondition(String aggregateProperty, AggregateType aggregateType, String[] groupByProperties) { this.groupByProperties = new ArrayList(); // 需要放在propertyMap初始化完成后执行 aggregateType(aggregateType); if (StringUtil.isNotEmpty(aggregateProperty)) { aggregateBy(aggregateProperty); } groupBy(groupByProperties); } public static AggregateCondition builder() { return new AggregateCondition(); } public AggregateCondition groupBy(String... groupByProperties) { if (groupByProperties != null && groupByProperties.length > 0) { this.groupByProperties.addAll(Arrays.asList(groupByProperties)); } return this; } public AggregateCondition aggregateBy(String aggregateProperty) { Assert.notEmpty(aggregateProperty, "aggregateProperty must have length; it must not be null or empty"); this.aggregateProperty = aggregateProperty; return this; } public AggregateCondition aliasName(String aggregateAliasName) { this.aggregateAliasName = aggregateAliasName; return this; } public AggregateCondition aggregateType(AggregateType aggregateType) { Assert.notNull(aggregateType, "aggregateType is required; it must not be null"); this.aggregateType = aggregateType; return this; } public String getAggregateProperty() { return aggregateProperty; } public String getAggregateAliasName() { return aggregateAliasName; } public List getGroupByProperties() { return groupByProperties; } public AggregateType getAggregateType() { return aggregateType; } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/aggregation/AggregateType.java ================================================ package tk.mybatis.mapper.additional.aggregation; /** * 聚合查询函数 * * @author liuchan */ public enum AggregateType { AVG, SUM, COUNT, MAX, MIN } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/aggregation/AggregationMapper.java ================================================ package tk.mybatis.mapper.additional.aggregation; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.SelectProvider; import java.util.List; /** * 通用聚合查询接口,特殊方法 * * @author liuchan */ @tk.mybatis.mapper.annotation.RegisterMapper public interface AggregationMapper { /** * 根据example和aggregateCondition进行聚合查询 * 分组不支持having条件过滤, 如需要建议使用xml文件 * * @param example * @param aggregateCondition 可以设置聚合查询的属性和分组属性 * @return 返回聚合查询属性和分组属性的值 */ @SelectProvider(type = AggregationProvider.class, method = "dynamicSQL") List selectAggregationByExample(@Param("example") Object example, @Param("aggregateCondition") AggregateCondition aggregateCondition); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/aggregation/AggregationProvider.java ================================================ package tk.mybatis.mapper.additional.aggregation; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.util.Assert; import tk.mybatis.mapper.util.SqlReservedWords; import tk.mybatis.mapper.util.StringUtil; import java.text.MessageFormat; import java.util.Map; /** * @author liuchan * @author liuzh */ public class AggregationProvider extends MapperTemplate { public AggregationProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public static String aggregationSelectClause(Class entityClass, String wrapKeyword, AggregateCondition condition) { Assert.notEmpty(condition.getAggregateProperty(), "aggregateProperty must have length; it must not be null or empty"); Assert.notNull(condition.getAggregateType(), "aggregateType is required; it must not be null"); EntityTable entityTable = EntityHelper.getEntityTable(entityClass); Map propertyMap = entityTable.getPropertyMap(); StringBuilder selectBuilder = new StringBuilder(); selectBuilder.append(condition.getAggregateType().name()); String columnName = propertyMap.get(condition.getAggregateProperty()).getColumn(); selectBuilder.append("(").append(columnName).append(")"); selectBuilder.append(" AS "); if (StringUtil.isNotEmpty(condition.getAggregateAliasName())) { selectBuilder.append(condition.getAggregateAliasName()); } else { selectBuilder.append(wrapKeyword(wrapKeyword, condition.getAggregateProperty())); } if (condition.getGroupByProperties() != null && condition.getGroupByProperties().size() > 0) { for (String property : condition.getGroupByProperties()) { selectBuilder.append(", "); columnName = propertyMap.get(property).getColumn(); selectBuilder.append(columnName).append(" AS ").append(wrapKeyword(wrapKeyword, property)); } } return selectBuilder.toString(); } private static String wrapKeyword(String wrapKeyword, String columnName) { if (StringUtil.isNotEmpty(wrapKeyword) && SqlReservedWords.containsWord(columnName)) { return MessageFormat.format(wrapKeyword, columnName); } return columnName; } public static String aggregationGroupBy(Class entityClass, String wrapKeyword, AggregateCondition condition) { if (condition.getGroupByProperties() != null && condition.getGroupByProperties().size() > 0) { EntityTable entityTable = EntityHelper.getEntityTable(entityClass); Map propertyMap = entityTable.getPropertyMap(); StringBuilder groupByBuilder = new StringBuilder(); for (String property : condition.getGroupByProperties()) { if (groupByBuilder.length() == 0) { groupByBuilder.append(" GROUP BY "); } else { groupByBuilder.append(", "); } groupByBuilder.append(propertyMap.get(property).getColumn()); } return groupByBuilder.toString(); } return ""; } /** * 根据Example查询总数 * * @param ms * @return */ public String selectAggregationByExample(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); if (isCheckExampleEntityClass()) { sql.append(SqlHelper.exampleCheck(entityClass)); } sql.append("SELECT ${@tk.mybatis.mapper.additional.aggregation.AggregationProvider@aggregationSelectClause("); sql.append("@").append(entityClass.getName()).append("@class"); sql.append(", '").append(getConfig().getWrapKeyword()).append("'"); sql.append(", aggregateCondition"); sql.append(")} "); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.updateByExampleWhereClause()); sql.append(" ${@tk.mybatis.mapper.additional.aggregation.AggregationProvider@aggregationGroupBy("); sql.append("@").append(entityClass.getName()).append("@class"); sql.append(", '").append(getConfig().getWrapKeyword()).append("'"); sql.append(", aggregateCondition"); sql.append(")} "); sql.append(SqlHelper.exampleOrderBy("example", entityClass)); sql.append(SqlHelper.exampleForUpdate()); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/delete/DeleteByPropertyMapper.java ================================================ package tk.mybatis.mapper.additional.delete; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.weekend.Fn; /** * @param 不能为空 * @author jingkaihui * @date 2020/3/30 */ @RegisterMapper public interface DeleteByPropertyMapper { /** * 根据实体中的属性删除,条件使用等号 * * @param fn 属性 * @param value 属性值 * @return */ @DeleteProvider(type = DeletePropertyProvider.class, method = "dynamicSQL") int deleteByProperty(@Param("fn") Fn fn, @Param("value") Object value); /** * 根据实体中的属性删除,条件使用 in * * @param fn 属性 * @param value 属性值 * @return */ @DeleteProvider(type = DeletePropertyProvider.class, method = "dynamicSQL") int deleteInByProperty(@Param("fn") Fn fn, @Param("values") Object value); /** * 根据属性及对应值进行删除,删除条件使用 between * * @param fn 属性 * @param begin 开始值 * @param end 开始值 * @return */ @SelectProvider(type = DeletePropertyProvider.class, method = "dynamicSQL") int deleteBetweenByProperty(@Param("fn") Fn fn, @Param("begin") Object begin, @Param("end") Object end); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/delete/DeletePropertyProvider.java ================================================ package tk.mybatis.mapper.additional.delete; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.util.MetaObjectUtil; /** * @author jingkaihui * @date 2020/3/30 */ public class DeletePropertyProvider extends MapperTemplate { public DeletePropertyProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 根据属性删除,条件使用等号 * * @param ms * @return */ public String deleteByProperty(MappedStatement ms) { String propertyHelper = DeletePropertyProvider.class.getName(); Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); // 如果是逻辑删除,则修改为更新表,修改逻辑删除字段的值 if (SqlHelper.hasLogicDeleteColumn(entityClass)) { sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(""); sql.append(SqlHelper.logicDeleteColumnEqualsValue(entityClass, true)); sql.append(""); MetaObjectUtil.forObject(ms).setValue("sqlCommandType", SqlCommandType.UPDATE); } else { sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); } sql.append("\n"); sql.append("\n"); String entityClassName = entityClass.getName(); //通过实体类名获取运行时属性对应的字段 String ognl = new StringBuilder("${@") .append(propertyHelper) .append("@getColumnByProperty(@java.lang.Class@forName(\"") .append(entityClassName) .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString(); sql.append(ognl + " = #{value}\n"); sql.append("\n"); sql.append(""); return sql.toString(); } /** * 根据属性删除,条件使用等号 * * @param ms * @return */ public String deleteInByProperty(MappedStatement ms) { String propertyHelper = DeletePropertyProvider.class.getName(); Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); // 如果是逻辑删除,则修改为更新表,修改逻辑删除字段的值 if (SqlHelper.hasLogicDeleteColumn(entityClass)) { sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(""); sql.append(SqlHelper.logicDeleteColumnEqualsValue(entityClass, true)); sql.append(""); MetaObjectUtil.forObject(ms).setValue("sqlCommandType", SqlCommandType.UPDATE); } else { sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); } sql.append("\n"); String entityClassName = entityClass.getName(); String sqlSegment = "${@" + propertyHelper + "@getColumnByProperty(@java.lang.Class@forName(\"" + entityClassName + "\")," + "@tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))} in" + "\n" + "#{obj}\n" + "\n"; sql.append(sqlSegment); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据属性删除,删除条件使用 between * * @param ms * @return */ public String deleteBetweenByProperty(MappedStatement ms) { String propertyHelper = DeletePropertyProvider.class.getName(); Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); // 如果是逻辑删除,则修改为更新表,修改逻辑删除字段的值 if (SqlHelper.hasLogicDeleteColumn(entityClass)) { sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(""); sql.append(SqlHelper.logicDeleteColumnEqualsValue(entityClass, true)); sql.append(""); MetaObjectUtil.forObject(ms).setValue("sqlCommandType", SqlCommandType.UPDATE); } else { sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); } sql.append("\n"); String entityClassName = entityClass.getName(); String sqlSegment = "${@" + propertyHelper + "@getColumnByProperty(@java.lang.Class@forName(\"" + entityClassName + "\")," + "@tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))} " + "between #{begin} and #{end}"; sql.append(sqlSegment); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据实体Class和属性名获取对应的表字段名 * * @param entityClass 实体Class对象 * @param property 属性名 * @return */ public static String getColumnByProperty(Class entityClass, String property) { EntityTable entityTable = EntityHelper.getEntityTable(entityClass); EntityColumn entityColumn = entityTable.getPropertyMap().get(property); return entityColumn.getColumn(); } public static boolean isNull(Object value, boolean safeDelete) { boolean isNull = false; if (safeDelete) { if (null == value) { throw new MapperException("安全删除模式下,不允许执行不带查询条件的 delete 方法"); } } else { if (null == value) { isNull = true; } } return isNull; } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/dialect/oracle/InsertListMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.dialect.oracle; import org.apache.ibatis.annotations.InsertProvider; import tk.mybatis.mapper.annotation.KeySql; import java.util.List; /** *

Oracle批量插入 *

支持@{@link KeySql#genId()},不支持@{@link KeySql#sql()} *

因INSERT ALL语法不支持序列,可手工获取序列并设置至Entity或绑定触发器 * * @author qrqhuangcy * @date 2018-11-16 */ @tk.mybatis.mapper.annotation.RegisterMapper public interface InsertListMapper { /** *

生成如下批量SQL: *

INSERT ALL *

INTO demo_country ( country_id,country_name,country_code ) VALUES ( ?,?,? ) *

INTO demo_country ( country_id,country_name,country_code ) VALUES ( ?,?,? ) *

INTO demo_country ( country_id,country_name,country_code ) VALUES ( ?,?,? ) *

SELECT 1 FROM DUAL * * @param recordList * @return */ @InsertProvider(type = OracleProvider.class, method = "dynamicSQL") int insertList(List recordList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/dialect/oracle/OracleMapper.java ================================================ package tk.mybatis.mapper.additional.dialect.oracle; /** * @description: Oracle独有方法 * @author: qrqhuangcy * @date: 2018-11-15 **/ @tk.mybatis.mapper.annotation.RegisterMapper public interface OracleMapper extends InsertListMapper { } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/dialect/oracle/OracleProvider.java ================================================ package tk.mybatis.mapper.additional.dialect.oracle; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Set; /** * @description: Oracle实现类 * @author: qrqhuangcy * @date: 2018-11-15 **/ public class OracleProvider extends MapperTemplate { public OracleProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * * INSERT ALL * * INTO demo_country * country_id,country_name,country_code, * VALUES * * * #{record.countryId},#{record.countryName},#{record.countryCode}, * * * SELECT 1 FROM DUAL * * @param ms * @return */ public String insertList(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //开始拼sql StringBuilder sql = new StringBuilder(); sql.append("\n"); sql.append("INSERT ALL\n"); sql.append("\n"); String tableName = SqlHelper.getDynamicTableName(entityClass, tableName(entityClass), "list[0]"); String columns = SqlHelper.insertColumns(entityClass, false, false, false); sql.append(" INTO ").append(tableName).append(" ").append(columns).append("\n"); sql.append(" VALUES "); sql.append(""); Set columnList = EntityHelper.getColumns(entityClass); //单独增加对 genId 方式的支持 for (EntityColumn column : columnList) { if (column.getGenIdClass() != null) { sql.append(""); } } //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnList) { if (column.isInsertable()) { sql.append(column.getColumnHolder("record") + ","); } } sql.append("\n"); sql.append("\n"); sql.append("SELECT 1 FROM DUAL"); //System.out.println("sql mapper: \n" + sql.toString()); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/idlist/DeleteByIdListMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.idlist; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 通用Mapper接口,根据idList删除 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface DeleteByIdListMapper { /** * 根据主键字符串进行删除,类中只有存在一个带有@Id注解的字段 * * @param idList * @return */ @DeleteProvider(type = IdListProvider.class, method = "dynamicSQL") int deleteByIdList(@Param("idList") List idList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/idlist/IdListMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.idlist; /** * 通用Mapper接口,根据idList操作 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface IdListMapper extends SelectByIdListMapper, DeleteByIdListMapper { } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/idlist/IdListProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.idlist; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.List; import java.util.Set; /** * 通过 ids 字符串的各种操作 *

* ids 如 "1,2,3" * * @author liuzh */ public class IdListProvider extends MapperTemplate { public IdListProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 保证 idList 不能为空 * * @param list * @param errorMsg */ public static void notEmpty(List list, String errorMsg) { if (list == null || list.size() == 0) { throw new MapperException(errorMsg); } } /** * 根据主键字符串进行删除,类中只有存在一个带有@Id注解的字段 * * @param ms * @return */ public String deleteByIdList(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.deleteFromTable(entityClass, tableName(entityClass))); appendWhereIdList(sql, entityClass, getConfig().isSafeDelete()); return sql.toString(); } /** * 根据主键字符串进行查询,类中只有存在一个带有@Id注解的字段 * * @param ms * @return */ public String selectByIdList(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //将返回值修改为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); appendWhereIdList(sql, entityClass, isNotEmpty()); return sql.toString(); } /** * 拼接条件 * * @param sql * @param entityClass */ private void appendWhereIdList(StringBuilder sql, Class entityClass, boolean notEmpty) { Set columnList = EntityHelper.getPKColumns(entityClass); if (columnList.size() == 1) { EntityColumn column = columnList.iterator().next(); if (notEmpty) { sql.append(""); } sql.append(""); sql.append(""); sql.append("#{id}"); sql.append(""); sql.append(""); } else { throw new MapperException("继承 ByIdList 方法的实体类[" + entityClass.getName() + "]中必须只有一个带有 @Id 注解的字段"); } } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/idlist/SelectByIdListMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.idlist; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.SelectProvider; import java.util.List; /** * 通用Mapper接口,根据ids查询 * * @param 不能为空 * @author liuzh */ @tk.mybatis.mapper.annotation.RegisterMapper public interface SelectByIdListMapper { /** * 根据主键字符串进行查询,类中只有存在一个带有@Id注解的字段 * * @param idList * @return */ @SelectProvider(type = IdListProvider.class, method = "dynamicSQL") List selectByIdList(@Param("idList") List idList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/insert/InsertListMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.insert; import org.apache.ibatis.annotations.InsertProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; /** * 通用Mapper接口,特殊方法,批量插入,支持批量插入的数据库都可以使用,例如mysql,h2等 * * @param 不能为空 * @author liuzh * @since 3.5.0 */ @RegisterMapper public interface InsertListMapper { /** * 批量插入,支持批量插入的数据库可以使用,例如MySQL,H2等 *

* 不支持主键策略,插入前需要设置好主键的值 *

* 特别注意:2018-04-22 后,该方法支持 @KeySql 注解的 genId 方式 * * @param recordList * @return */ @InsertProvider(type = InsertListProvider.class, method = "dynamicSQL") int insertList(List recordList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/insert/InsertListProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.insert; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Set; /** * @author liuzh */ public class InsertListProvider extends MapperTemplate { public InsertListProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 批量插入 * * @param ms */ public String insertList(MappedStatement ms) { final Class entityClass = getEntityClass(ms); //开始拼sql StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass), "list[0]")); sql.append(SqlHelper.insertColumns(entityClass, false, false, false)); sql.append(" VALUES "); sql.append(""); sql.append(""); //获取全部列 Set columnList = EntityHelper.getColumns(entityClass); //获取逻辑删除列 EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); //单独增加对 genId 方式的支持 for (EntityColumn column : columnList) { if (column.getGenIdClass() != null) { sql.append(""); } } //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnList) { if (!column.isInsertable()) { continue; } if (logicDeleteColumn != null && logicDeleteColumn == column) { sql.append(SqlHelper.getLogicDeletedValue(column, false)).append(","); continue; } sql.append(column.getColumnHolder("record") + ","); } sql.append(""); sql.append(""); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/select/SelectByPropertyMapper.java ================================================ package tk.mybatis.mapper.additional.select; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.weekend.Fn; import java.util.List; /** * 根据属性查询接口 * * @param 不能为空 * @author jingkaihui * @date 2019/10/11 */ @RegisterMapper public interface SelectByPropertyMapper { /** * 根据属性及对应值进行查询,只能有一个返回值,有多个结果时抛出异常,查询条件使用等号 * * @param fn 查询属性 * @param value 属性值 * @return */ @SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL") T selectOneByProperty(@Param("fn") Fn fn, @Param("value") Object value); /** * 根据属性及对应值进行查询,有多个返回值,查询条件使用等号 * * @param fn 查询属性 * @param value 属性值 * @return */ @SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL") List selectByProperty(@Param("fn") Fn fn, @Param("value") Object value); /** * 根据属性及对应值进行查询,查询条件使用 in * * @param fn 查询属性 * @param values 属性值集合,集合不能空 * @return */ @SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL") List selectInByProperty(@Param("fn") Fn fn, @Param("values") List values); /** * 根据属性及对应值进行查询,查询条件使用 between * * @param fn 查询属性 * @param begin 开始值 * @param end 开始值 * @return */ @SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL") List selectBetweenByProperty(@Param("fn") Fn fn, @Param("begin") Object begin, @Param("end") Object end); /** * 根据属性及对应值进行查询,检查是否存在对应记录,查询条件使用等号 * * @param fn 查询属性 * @param value 属性值 * @return */ @SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL") boolean existsWithProperty(@Param("fn") Fn fn, @Param("value") Object value); /** * 根据属性及对应值进行查询,统计符合条件的记录数,查询条件使用等号 * * @param fn 查询属性 * @param value 属性值 * @return */ @SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL") int selectCountByProperty(@Param("fn") Fn fn, @Param("value") Object value); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/select/SelectPropertyProvider.java ================================================ package tk.mybatis.mapper.additional.select; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.util.StringUtil; import java.util.Objects; /** * @author jingkaihui * @date 2019/10/11 */ public class SelectPropertyProvider extends MapperTemplate { private static final Log log = LogFactory.getLog(SelectPropertyProvider.class); public SelectPropertyProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * Ba * 根据属性查询,只能有一个返回值,有多个结果时抛出异常,查询条件使用等号 * * @param ms * @return */ public String selectOneByProperty(MappedStatement ms) { String propertyHelper = SelectPropertyProvider.class.getName(); Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append("\n"); sql.append("\n"); String entityClassName = entityClass.getName(); //通过实体类名获取运行时属性对应的字段 String ognl = new StringBuilder("${@") .append(propertyHelper) .append("@getColumnByProperty(@java.lang.Class@forName(\"") .append(entityClassName) .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString(); sql.append(ognl + " = #{value}\n"); sql.append("\n"); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据属性查询,查询条件使用等号 * * @param ms * @return */ public String selectByProperty(MappedStatement ms) { String propertyHelper = SelectPropertyProvider.class.getName(); Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append("\n"); sql.append("\n"); String entityClassName = entityClass.getName(); //通过实体类名获取运行时属性对应的字段 String ognl = new StringBuilder("${@") .append(propertyHelper) .append("@getColumnByProperty(@java.lang.Class@forName(\"") .append(entityClassName) .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString(); sql.append(ognl + " = #{value}\n"); sql.append("\n"); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据属性查询,查询条件使用 in * * @param ms * @return */ public String selectInByProperty(MappedStatement ms) { Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append("\n"); String entityClassName = entityClass.getName(); String propertyHelper = SelectPropertyProvider.class.getName(); String sqlSegment = "${@" + propertyHelper + "@getColumnByProperty(@java.lang.Class@forName(\"" + entityClassName + "\")," + "@tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))} in" + "\n" + "#{obj}\n" + "\n"; sql.append(sqlSegment); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据属性查询,查询条件使用 between * * @param ms * @return */ public String selectBetweenByProperty(MappedStatement ms) { Class entityClass = getEntityClass(ms); //修改返回值类型为实体类型 setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectAllColumns(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append("\n"); String entityClassName = entityClass.getName(); String propertyHelper = SelectPropertyProvider.class.getName(); String sqlSegment = "${@" + propertyHelper + "@getColumnByProperty(@java.lang.Class@forName(\"" + entityClassName + "\")," + "@tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))} " + "between #{begin} and #{end}"; sql.append(sqlSegment); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据属性查询总数,查询条件使用等号 * * @param ms * @return */ public String existsWithProperty(MappedStatement ms) { String propertyHelper = SelectPropertyProvider.class.getName(); Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectCountExists(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append("\n"); sql.append("\n"); String entityClassName = entityClass.getName(); //通过实体类名获取运行时属性对应的字段 String ognl = new StringBuilder("${@") .append(propertyHelper) .append("@getColumnByProperty(@java.lang.Class@forName(\"") .append(entityClassName) .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString(); sql.append(ognl + " = #{value}\n"); sql.append("\n"); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据属性查询总数,查询条件使用等号 * * @param ms * @return */ public String selectCountByProperty(MappedStatement ms) { Class entityClass = getEntityClass(ms); String propertyHelper = SelectPropertyProvider.class.getName(); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.selectCount(entityClass)); sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); sql.append("\n"); sql.append("\n"); String entityClassName = entityClass.getName(); //通过实体类名获取运行时属性对应的字段 String ognl = new StringBuilder("${@") .append(propertyHelper) .append("@getColumnByProperty(@java.lang.Class@forName(\"") .append(entityClassName) .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString(); sql.append(ognl + " = #{value}\n"); sql.append("\n"); // 逻辑删除的未删除查询条件 sql.append(SqlHelper.whereLogicDelete(entityClass, false)); sql.append(""); return sql.toString(); } /** * 根据实体Class和属性名获取对应的表字段名 * * @param entityClass 实体Class对象 * @param property 属性名 * @return */ public static String getColumnByProperty(Class entityClass, String property) { EntityTable entityTable = EntityHelper.getEntityTable(entityClass); EntityColumn entityColumn = entityTable.getPropertyMap().get(property); return entityColumn.getColumn(); } /** * 判断是否需要拼接 where 条件 * * @param value * @param notEmpty * @return */ public static boolean existsWhereCondition(Object value, boolean notEmpty) { boolean appendWhereCondition = true; if (Objects.isNull(value)) { log.warn("value is null! this will case no conditions after where keyword"); } else { if (String.class.equals(value.getClass()) && notEmpty && StringUtil.isEmpty(value.toString())) { // 如果 value 是 String 类型,则根据是否允许为空串做进一步校验来决定是否拼接 where 条件 appendWhereCondition = false; } } return appendWhereCondition; } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/select/SelectSpecifyColumnsMapper.java ================================================ package tk.mybatis.mapper.additional.select; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.SelectProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.weekend.Fn; import java.util.List; /** * 查询指定字段 * * @param 不能为空 * * @author xiaodiwangjie * @date 2020/10/24 */ @RegisterMapper public interface SelectSpecifyColumnsMapper { /** * 根据条件查询实体, 并指定字段 * * @param record 查询实体条件 * @param columns 指定的返回字段 * @return */ @SelectProvider( type = SelectSpecifyColumnsProvider.class, method = "dynamicSQL" ) List selectByColumns(@Param("record") T record, @Param("columns") List columns); /** * 根据条件查询实体, 并指定属性 * * @param record 查询实体条件 * @param fns 指定的返回实体属性 * @return */ @SelectProvider( type = SelectSpecifyColumnsProvider.class, method = "dynamicSQL" ) List selectByPropertys(@Param("record") T record, @Param("fns") List> fns); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/select/SelectSpecifyColumnsProvider.java ================================================ package tk.mybatis.mapper.additional.select; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.annotation.Version; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Iterator; import java.util.Set; /** * @author xiaodiwangjie * @date 2020/10/24 */ public class SelectSpecifyColumnsProvider extends MapperTemplate { public SelectSpecifyColumnsProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String selectByColumns(MappedStatement ms) { Class entityClass = this.getEntityClass(ms); this.setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append("SELECT "); sql.append(""); sql.append("${item}"); sql.append(""); sql.append(SqlHelper.fromTable(entityClass, this.tableName(entityClass))); sql.append(whereAllIfColumns(entityClass, this.isNotEmpty(), false)); sql.append(SqlHelper.orderByDefault(entityClass)); return sql.toString(); } public String selectByPropertys(MappedStatement ms) { String propertyHelper = SelectSpecifyColumnsProvider.class.getName(); Class entityClass = this.getEntityClass(ms); this.setResultType(ms, entityClass); StringBuilder sql = new StringBuilder(); sql.append("SELECT "); String entityClassName = entityClass.getName(); sql.append(""); String ognl = new StringBuilder("${@") .append(propertyHelper) .append("@getColumnByProperty(@java.lang.Class@forName(\"") .append(entityClassName) .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(item))}").toString(); sql.append(ognl); sql.append(""); sql.append(SqlHelper.fromTable(entityClass, this.tableName(entityClass))); sql.append(whereAllIfColumns(entityClass, this.isNotEmpty(), false)); sql.append(SqlHelper.orderByDefault(entityClass)); return sql.toString(); } public static String whereAllIfColumns(Class entityClass, boolean empty, boolean useVersion) { StringBuilder sql = new StringBuilder(); sql.append(""); Set columnSet = EntityHelper.getColumns(entityClass); Iterator var5 = columnSet.iterator(); while (true) { EntityColumn column; do { if (!var5.hasNext()) { if (useVersion) { sql.append(SqlHelper.whereVersion(entityClass)); } sql.append(""); return sql.toString(); } column = (EntityColumn) var5.next(); } while (useVersion && column.getEntityField().isAnnotationPresent(Version.class)); sql.append(getIfNotNull(column, " AND " + getColumnEqualsHolder(column), empty)); } } public static String getIfNotNull(EntityColumn column, String contents, boolean empty) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(contents); sql.append(""); return sql.toString(); } public static String getColumnEqualsHolder(EntityColumn column) { return column.getColumn() + " = " + getColumnHolder(column); } public static String getColumnHolder(EntityColumn column) { StringBuffer sb = new StringBuffer("#{"); sb.append("record.").append(column.getProperty()); if (column.getJdbcType() != null) { sb.append(", jdbcType="); sb.append(column.getJdbcType().toString()); } if (column.getTypeHandler() != null) { sb.append(", typeHandler="); sb.append(column.getTypeHandler().getCanonicalName()); } if (column.isUseJavaType() && !column.getJavaType().isArray()) { sb.append(", javaType="); sb.append(column.getJavaType().getCanonicalName()); } sb.append("}"); return sb.toString(); } /** * 根据实体Class和属性名获取对应的表字段名 * @param entityClass 实体Class对象 * @param property 属性名 * @return */ public static String getColumnByProperty(Class entityClass, String property) { EntityTable entityTable = EntityHelper.getEntityTable(entityClass); EntityColumn entityColumn = entityTable.getPropertyMap().get(property); return entityColumn.getColumn(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdateMapper.java ================================================ package tk.mybatis.mapper.additional.update.batch; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; @RegisterMapper public interface BatchUpdateMapper { @UpdateProvider( type = BatchUpdateProvider.class, method = "dynamicSQL" ) void batchUpdate(@Param("list") List recordList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdateProvider.java ================================================ package tk.mybatis.mapper.additional.update.batch; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; public class BatchUpdateProvider extends MapperTemplate { public BatchUpdateProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String batchUpdate(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.updateSetColumns(entityClass, "record", false, false)); sql.append(SqlHelper.wherePKColumns(entityClass, "record", true)); sql.append(""); return sql.toString(); } public String batchUpdateSelective(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(SqlHelper.updateSetColumns(entityClass, "record", true, isNotEmpty())); sql.append(SqlHelper.wherePKColumns(entityClass, "record", true)); sql.append(""); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdateSelectiveMapper.java ================================================ package tk.mybatis.mapper.additional.update.batch; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; @RegisterMapper public interface BatchUpdateSelectiveMapper { @UpdateProvider( type = BatchUpdateProvider.class, method = "dynamicSQL" ) void batchUpdateSelective(@Param("list") List recordList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/differ/UpdateByDifferMapper.java ================================================ package tk.mybatis.mapper.additional.update.differ; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; /** * 差异更新 * * @param 不能为空 * @author liuzh * @since 4.0.4 */ @RegisterMapper public interface UpdateByDifferMapper { /** * 根据 old 和 newer 进行差异更新,当对应某个字段值不同时才会更新 * * @param old * @param newer * @return */ @UpdateProvider(type = UpdateByDifferProvider.class, method = "dynamicSQL") int updateByDiffer(@Param("old") T old, @Param("newer") T newer); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/differ/UpdateByDifferProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.update.differ; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.annotation.Version; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.version.VersionException; import java.util.Set; /** * @author liuzh */ public class UpdateByDifferProvider extends MapperTemplate { public static final String OLD = "old"; public static final String NEWER = "newer"; public UpdateByDifferProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } /** * 差异更新 * * @param ms */ public String updateByDiffer(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); sql.append(updateSetColumnsByDiffer(entityClass)); sql.append(wherePKColumns(entityClass, true)); return sql.toString(); } /** * where主键条件 * * @param entityClass * @return */ public String wherePKColumns(Class entityClass, boolean useVersion) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getPKColumns(entityClass); //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { sql.append(" AND " + column.getColumnEqualsHolder(NEWER)); } if (useVersion) { sql.append(whereVersion(entityClass)); } sql.append(""); return sql.toString(); } /** * 乐观锁字段条件 * * @param entityClass * @return */ public String whereVersion(Class entityClass) { Set columnSet = EntityHelper.getColumns(entityClass); boolean hasVersion = false; String result = ""; for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(Version.class)) { if (hasVersion) { throw new VersionException(entityClass.getName() + " 中包含多个带有 @Version 注解的字段,一个类中只能存在一个带有 @Version 注解的字段!"); } hasVersion = true; result = " AND " + column.getColumnEqualsHolder(NEWER); } } return result; } /** * update set列 * * @param entityClass * @return */ public String updateSetColumnsByDiffer(Class entityClass) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); //对乐观锁的支持 EntityColumn versionColumn = null; //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(Version.class)) { if (versionColumn != null) { throw new VersionException(entityClass.getName() + " 中包含多个带有 @Version 注解的字段,一个类中只能存在一个带有 @Version 注解的字段!"); } versionColumn = column; } if (!column.isId() && column.isUpdatable()) { if (column == versionColumn) { Version version = versionColumn.getEntityField().getAnnotation(Version.class); String versionClass = version.nextVersion().getName(); //version = ${@tk.mybatis.mapper.version@nextVersionClass("versionClass", version)} sql.append(column.getColumn()) .append(" = ${@tk.mybatis.mapper.version.VersionUtil@nextVersion(") .append("@").append(versionClass).append("@class, ") .append(NEWER).append('.').append(column.getProperty()).append(")},"); } else { //if old.xx != newer.xx sql.append(getIfNotEqual(column, column.getColumnEqualsHolder(NEWER) + ",")); } } } sql.append(""); return sql.toString(); } /** * 判断自动!=null的条件结构 * * @param column * @param contents * @return */ public String getIfNotEqual(EntityColumn column, String contents) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(contents); sql.append(""); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/force/UpdateByPrimaryKeySelectiveForceMapper.java ================================================ package tk.mybatis.mapper.additional.update.force; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; /** * @author qrqhuangcy * @Description: 通用Mapper接口, 非空字段强制更新 * @date 2018-06-26 */ @RegisterMapper public interface UpdateByPrimaryKeySelectiveForceMapper { /** * 根据主键更新属性不为null的值, 指定的属性(null值)会被强制更新 * * @param record * @param forceUpdateProperties * @return */ @UpdateProvider(type = UpdateByPrimaryKeySelectiveForceProvider.class, method = "dynamicSQL") int updateByPrimaryKeySelectiveForce(@Param("record") T record, @Param("forceUpdateProperties") List forceUpdateProperties); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/update/force/UpdateByPrimaryKeySelectiveForceProvider.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.update.force; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.annotation.Version; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import tk.mybatis.mapper.util.StringUtil; import tk.mybatis.mapper.version.VersionException; import java.util.Set; /** * @author qrqhuangcy * @Description: 通用Mapper接口, 更新, 强制,实现 * @date 2018-06-26 */ public class UpdateByPrimaryKeySelectiveForceProvider extends MapperTemplate { public static final String FORCE_UPDATE_PROPERTIES = "forceUpdateProperties"; public UpdateByPrimaryKeySelectiveForceProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String updateByPrimaryKeySelectiveForce(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass), "record")); sql.append(this.updateSetColumnsForce(entityClass, "record", true, isNotEmpty())); sql.append(SqlHelper.wherePKColumns(entityClass, "record", true)); return sql.toString(); } /** * update set列 * * @param entityClass * @param entityName 实体映射名 * @param notNull 是否判断!=null * @param notEmpty 是否判断String类型!='' * @return */ public String updateSetColumnsForce(Class entityClass, String entityName, boolean notNull, boolean notEmpty) { StringBuilder sql = new StringBuilder(); sql.append(""); //获取全部列 Set columnSet = EntityHelper.getColumns(entityClass); //对乐观锁的支持 EntityColumn versionColumn = null; //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值 for (EntityColumn column : columnSet) { if (column.getEntityField().isAnnotationPresent(Version.class)) { if (versionColumn != null) { throw new VersionException(entityClass.getName() + " 中包含多个带有 @Version 注解的字段,一个类中只能存在一个带有 @Version 注解的字段!"); } versionColumn = column; } if (!column.isId() && column.isUpdatable()) { if (column == versionColumn) { Version version = versionColumn.getEntityField().getAnnotation(Version.class); String versionClass = version.nextVersion().getName(); //version = ${@tk.mybatis.mapper.version@nextVersionClass("versionClass", version)} sql.append(column.getColumn()) .append(" = ${@tk.mybatis.mapper.version.VersionUtil@nextVersion(") .append("@").append(versionClass).append("@class, "); //虽然从函数调用上来看entityName必为"record",但还是判断一下 if (StringUtil.isNotEmpty(entityName)) { sql.append(entityName).append('.'); } sql.append(column.getProperty()).append(")},"); } else if (notNull) { sql.append(this.getIfNotNull(entityName, column, column.getColumnEqualsHolder(entityName) + ",", notEmpty)); } else { sql.append(column.getColumnEqualsHolder(entityName)).append(","); } } else if (column.isId() && column.isUpdatable()) { //set id = id, sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(","); } } sql.append(""); return sql.toString(); } /** * 判断自动!=null的条件结构 * * @param entityName * @param column * @param contents * @param empty * @return */ public String getIfNotNull(String entityName, EntityColumn column, String contents, boolean empty) { StringBuilder sql = new StringBuilder(); sql.append(""); sql.append(""); sql.append(contents); sql.append(""); //指定的字段会被强制更新 sql.append(""); sql.append(contents); sql.append(""); sql.append(""); sql.append(""); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/upsert/BatchUpsertMapper.java ================================================ package tk.mybatis.mapper.additional.upsert; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; @RegisterMapper public interface BatchUpsertMapper { @UpdateProvider( type = BatchUpsertProvider.class, method = "dynamicSQL" ) void batchUpsert(@Param("list") List recordList); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/upsert/BatchUpsertProvider.java ================================================ package tk.mybatis.mapper.additional.upsert; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Set; public class BatchUpsertProvider extends MapperTemplate { public BatchUpsertProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String batchUpsert(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(""); sql.append("INSERT INTO "); sql.append(tableName(entityClass)); Set columns = EntityHelper.getColumns(entityClass); String primaryKeyColumn = null; EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); sql.append(""); for (EntityColumn column : columns) { if (column.isId()) { primaryKeyColumn = column.getColumn(); } if (column.isInsertable()) { sql.append(column.getColumn() + ","); } } sql.append(""); sql.append(" VALUES "); sql.append(""); for (EntityColumn column : columns) { if (column.getGenIdClass() != null) { sql.append(""); } } for (EntityColumn column : columns) { if (!column.isInsertable()) { continue; } if (logicDeleteColumn != null && logicDeleteColumn == column) { sql.append(SqlHelper.getLogicDeletedValue(column, false)).append(","); continue; } sql.append(column.getColumnHolder("record") + ","); } sql.append(""); sql.append(" ON CONFLICT (" + primaryKeyColumn + ") DO UPDATE "); sql.append(SqlHelper.updateSetColumns(entityClass, "record", true, isNotEmpty())); sql.append(""); return sql.toString(); } } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/upsert/UpsertMapper.java ================================================ package tk.mybatis.mapper.additional.upsert; import org.apache.ibatis.annotations.UpdateProvider; import tk.mybatis.mapper.annotation.RegisterMapper; @RegisterMapper public interface UpsertMapper { @UpdateProvider( type = UpsertProvider.class, method = "dynamicSQL" ) void upsert(T record); } ================================================ FILE: extra/src/main/java/tk/mybatis/mapper/additional/upsert/UpsertProvider.java ================================================ package tk.mybatis.mapper.additional.upsert; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Set; public class UpsertProvider extends MapperTemplate { public UpsertProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String upsert(MappedStatement ms) { final Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(tableName(entityClass)); Set columns = EntityHelper.getColumns(entityClass); String primaryKeyColumn = null; EntityColumn logicDeleteColumn = SqlHelper.getLogicDeleteColumn(entityClass); sql.append(""); for (EntityColumn column : columns) { if (column.isId()) { primaryKeyColumn = column.getColumn(); } if (column.isInsertable()) { sql.append(column.getColumn() + ","); } } sql.append(""); sql.append(" VALUES "); sql.append(""); for (EntityColumn column : columns) { if (column.getGenIdClass() != null) { sql.append(""); } } for (EntityColumn column : columns) { if (!column.isInsertable()) { continue; } if (logicDeleteColumn != null && logicDeleteColumn == column) { sql.append(SqlHelper.getLogicDeletedValue(column, false)).append(","); continue; } sql.append(column.getColumnHolder() + ","); } sql.append(""); sql.append(" ON CONFLICT (" + primaryKeyColumn + ") DO UPDATE "); sql.append(SqlHelper.updateSetColumns(entityClass, null, true, isNotEmpty())); return sql.toString(); } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/BaseTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.sql.Connection; /** * 测试基类 * * @author liuzh */ public abstract class BaseTest { private SqlSessionFactory sqlSessionFactory; @Before public final void init() { try { Reader reader = getConfigFileAsReader(); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); reader.close(); //配置通用 Mapper configMapperHelper(); //执行初始化 SQL runSql(getSqlFileAsReader()); } catch (IOException e) { throw new RuntimeException(e); } } /** * 配置通用 Mapper */ protected void configMapperHelper() { SqlSession session = getSqlSession(); try { //创建一个MapperHelper MapperHelper mapperHelper = new MapperHelper(); //设置配置 mapperHelper.setConfig(getConfig()); //配置完成后,执行下面的操作 mapperHelper.processConfiguration(session.getConfiguration()); } finally { session.close(); } } /** * 执行 Sql * * @param reader */ protected void runSql(Reader reader) { if (reader == null) { return; } SqlSession sqlSession = getSqlSession(); try { Connection conn = sqlSession.getConnection(); ScriptRunner runner = new ScriptRunner(conn); runner.setLogWriter(null); runner.runScript(reader); try { reader.close(); } catch (IOException e) { } } finally { sqlSession.close(); } } /** * 获取 Mapper 配置 * * @return */ protected Config getConfig() { return new Config(); } /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = BaseTest.class.getResource("mybatis-config.xml"); return toReader(url); } ; /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = BaseTest.class.getResource("CreateDB.sql"); return toReader(url); } ; /** * 转为 Reader * * @param url * @return * @throws IOException */ protected Reader toReader(URL url) throws IOException { return Resources.getUrlAsReader(url.toString()); } /** * 获取Session * * @return */ protected SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional; import jakarta.persistence.Id; import java.io.Serializable; /** * @author liuzh */ public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id private Long id; private String countryname; private String countrycode; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } @Override public String toString() { return "Country{" + "id=" + id + ", countryname='" + countryname + '\'' + ", countrycode='" + countrycode + '\'' + '}'; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/CountryMapper.java ================================================ package tk.mybatis.mapper.additional; import tk.mybatis.mapper.additional.idlist.IdListMapper; public interface CountryMapper extends IdListMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/CreateDB.sql ================================================ drop table country if exists; create table country ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) DEFAULT 'HH', version INTEGER DEFAULT 1 NOT NULL ); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (13, 'Bahamas', 'BS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (14, 'Bahrain', 'BH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (15, 'Bangladesh', 'BD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (16, 'Barbados', 'BB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (17, 'Belarus', 'BY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (18, 'Belgium', 'BE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (19, 'Belize', 'BZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (20, 'Benin', 'BJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (21, 'Bermuda Is.', 'BM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (22, 'Bolivia', 'BO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (23, 'Botswana', 'BW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (24, 'Brazil', 'BR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (25, 'Brunei', 'BN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (26, 'Bulgaria', 'BG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (27, 'Burkina-faso', 'BF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (28, 'Burma', 'MM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (29, 'Burundi', 'BI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (30, 'Cameroon', 'CM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (31, 'Canada', 'CA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (32, 'Central African Republic', 'CF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (33, 'Chad', 'TD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (34, 'Chile', 'CL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (35, 'China', 'CN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (36, 'Colombia', 'CO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (37, 'Congo', 'CG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (38, 'Cook Is.', 'CK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (39, 'Costa Rica', 'CR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (40, 'Cuba', 'CU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (41, 'Cyprus', 'CY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (42, 'Czech Republic', 'CZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (43, 'Denmark', 'DK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (44, 'Djibouti', 'DJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (45, 'Dominica Rep.', 'DO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (46, 'Ecuador', 'EC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (47, 'Egypt', 'EG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (48, 'EI Salvador', 'SV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (49, 'Estonia', 'EE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (50, 'Ethiopia', 'ET', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (51, 'Fiji', 'FJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (52, 'Finland', 'FI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (53, 'France', 'FR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (54, 'French Guiana', 'GF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (55, 'Gabon', 'GA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (56, 'Gambia', 'GM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (57, 'Georgia', 'GE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (58, 'Germany', 'DE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (59, 'Ghana', 'GH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (60, 'Gibraltar', 'GI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (61, 'Greece', 'GR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (62, 'Grenada', 'GD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (63, 'Guam', 'GU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (64, 'Guatemala', 'GT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (65, 'Guinea', 'GN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (66, 'Guyana', 'GY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (67, 'Haiti', 'HT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (68, 'Honduras', 'HN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (69, 'Hongkong', 'HK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (70, 'Hungary', 'HU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (71, 'Iceland', 'IS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (72, 'India', 'IN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (73, 'Indonesia', 'ID', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (74, 'Iran', 'IR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (75, 'Iraq', 'IQ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (76, 'Ireland', 'IE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (77, 'Israel', 'IL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (78, 'Italy', 'IT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (79, 'Jamaica', 'JM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (80, 'Japan', 'JP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (81, 'Jordan', 'JO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (82, 'Kampuchea (Cambodia )', 'KH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (83, 'Kazakstan', 'KZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (84, 'Kenya', 'KE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (85, 'Korea', 'KR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (86, 'Kuwait', 'KW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (87, 'Kyrgyzstan', 'KG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (88, 'Laos', 'LA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (89, 'Latvia', 'LV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (90, 'Lebanon', 'LB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (91, 'Lesotho', 'LS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (92, 'Liberia', 'LR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (93, 'Libya', 'LY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (94, 'Liechtenstein', 'LI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (95, 'Lithuania', 'LT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (96, 'Luxembourg', 'LU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (97, 'Macao', 'MO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (98, 'Madagascar', 'MG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (99, 'Malawi', 'MW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (100, 'Malaysia', 'MY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (101, 'Maldives', 'MV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (102, 'Mali', 'ML', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (103, 'Malta', 'MT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (104, 'Mauritius', 'MU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (105, 'Mexico', 'MX', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (106, 'Moldova, Republic of', 'MD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (107, 'Monaco', 'MC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (108, 'Mongolia', 'MN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (109, 'Montserrat Is', 'MS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (110, 'Morocco', 'MA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (111, 'Mozambique', 'MZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (112, 'Namibia', 'NA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (113, 'Nauru', 'NR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (114, 'Nepal', 'NP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (115, 'Netherlands', 'NL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (116, 'New Zealand', 'NZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (117, 'Nicaragua', 'NI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (118, 'Niger', 'NE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (119, 'Nigeria', 'NG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (120, 'North Korea', 'KP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (121, 'Norway', 'NO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (122, 'Oman', 'OM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (123, 'Pakistan', 'PK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (124, 'Panama', 'PA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (125, 'Papua New Cuinea', 'PG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (126, 'Paraguay', 'PY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (127, 'Peru', 'PE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (128, 'Philippines', 'PH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (129, 'Poland', 'PL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (130, 'French Polynesia', 'PF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (131, 'Portugal', 'PT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (132, 'Puerto Rico', 'PR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (133, 'Qatar', 'QA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (134, 'Romania', 'RO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (135, 'Russia', 'RU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (136, 'Saint Lueia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (137, 'Saint Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (138, 'San Marino', 'SM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (139, 'Sao Tome and Principe', 'ST', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (140, 'Saudi Arabia', 'SA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (141, 'Senegal', 'SN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (142, 'Seychelles', 'SC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (143, 'Sierra Leone', 'SL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (144, 'Singapore', 'SG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (145, 'Slovakia', 'SK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (146, 'Slovenia', 'SI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (147, 'Solomon Is', 'SB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (148, 'Somali', 'SO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (149, 'South Africa', 'ZA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (150, 'Spain', 'ES', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (151, 'Sri Lanka', 'LK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (152, 'St.Lucia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (153, 'St.Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (154, 'Sudan', 'SD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (155, 'Suriname', 'SR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (156, 'Swaziland', 'SZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (157, 'Sweden', 'SE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (158, 'Switzerland', 'CH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (159, 'Syria', 'SY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (160, 'Taiwan', 'TW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (161, 'Tajikstan', 'TJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (162, 'Tanzania', 'TZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (163, 'Thailand', 'TH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (164, 'Togo', 'TG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (165, 'Tonga', 'TO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (166, 'Trinidad and Tobago', 'TT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (167, 'Tunisia', 'TN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (168, 'Turkey', 'TR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (169, 'Turkmenistan', 'TM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (170, 'Uganda', 'UG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (171, 'Ukraine', 'UA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (172, 'United Arab Emirates', 'AE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (173, 'United Kiongdom', 'GB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (174, 'United States of America', 'US', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (175, 'Uruguay', 'UY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (176, 'Uzbekistan', 'UZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (177, 'Venezuela', 'VE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (178, 'Vietnam', 'VN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (179, 'Yemen', 'YE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (180, 'Yugoslavia', 'YU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (181, 'Zimbabwe', 'ZW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (182, 'Zaire', 'ZR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (183, 'Zambia', 'ZM', 1); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/AggregationHumpTest.java ================================================ package tk.mybatis.mapper.additional.aggregation; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.Example; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.List; public class AggregationHumpTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } @Override protected Config getConfig() { Config config = super.getConfig(); // 开启驼峰转下划线,模拟真实环境中可能出现的问题 config.setStyle(Style.camelhump); return config; } @Test public void testAggregationWithCamelHump() { SqlSession sqlSession = getSqlSession(); try { UserHumpMapper mapper = sqlSession.getMapper(UserHumpMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder() .aggregateBy("id") // id -> id .aliasName("total") .aggregateType(AggregateType.COUNT) .groupBy("userRole"); // userRole -> user_role Example example = new Example(UserHump.class); List list = mapper.selectAggregationByExample(example, aggregateCondition); // 应该有 2 组: Admin 和 USER Assert.assertEquals(2, list.size()); // 验证 userRole 是否有值 // 如果 AggregationProvider 依然使用 alias AS user_role (columnName), // 在 mapUnderscoreToCamelCase=false (default) 的情况下,UserHump.userRole 属性将为 null。 // 只有当 AggregationProvider 使用 alias AS userRole (propertyName) 时,MyBatis 才能自动映射。 for (UserHump user : list) { Assert.assertNotNull("userRole should not be null", user.getUserRole()); Assert.assertTrue( "userRole should be Admin or USER", "Admin".equals(user.getUserRole()) || "USER".equals(user.getUserRole()) ); } // 所以,如果我要断言聚合值,我应该把 aliasName 设置为 "aggregation"。 } finally { sqlSession.close(); } } @Test public void testAggregationValueWithCamelHump() { SqlSession sqlSession = getSqlSession(); try { UserHumpMapper mapper = sqlSession.getMapper(UserHumpMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder() .aggregateBy("id") .aliasName("aggregation") .aggregateType(AggregateType.COUNT) .groupBy("userRole"); Example example = new Example(UserHump.class); example.setOrderByClause("user_role asc"); // 数据库列名 List list = mapper.selectAggregationByExample(example, aggregateCondition); Assert.assertEquals(2, list.size()); // Admin 有 3 个 (1,2,3) // USER 有 3 个 (4,5,6) for (UserHump u : list) { Assert.assertEquals(new Long(3), u.getAggregation()); Assert.assertNotNull(u.getUserRole()); } } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/AggregationMapperTest.java ================================================ package tk.mybatis.mapper.additional.aggregation; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import tk.mybatis.mapper.entity.Example; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.List; public class AggregationMapperTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } ; /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } ; @Test public void testCount() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder(). aggregateBy("id").aliasName("total").aggregateType(AggregateType.COUNT).groupBy("role"); Example example = new Example(User.class); List m = mapper.selectAggregationByExample(example, aggregateCondition); Assert.assertEquals(2, m.size()); } finally { sqlSession.close(); } } @Test public void testAvg() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder(). aggregateBy("id").aggregateType(AggregateType.AVG); Example example = new Example(User.class); List m = mapper.selectAggregationByExample(example, aggregateCondition); Assert.assertEquals(1, m.size()); Assert.assertEquals(new Long(3), m.get(0).getId()); } finally { sqlSession.close(); } } @Test public void testSum() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder(). aggregateBy("id").aliasName("aggregation").aggregateType(AggregateType.SUM); Example example = new Example(User.class); List m = mapper.selectAggregationByExample(example, aggregateCondition); Assert.assertEquals(1, m.size()); Assert.assertEquals(new Long(21), m.get(0).getAggregation()); } finally { sqlSession.close(); } } @Test public void testMax() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder(). aggregateBy("id").aliasName("aggregation").aggregateType(AggregateType.MAX).groupBy("role"); Example example = new Example(User.class); example.setOrderByClause("role desc"); List m = mapper.selectAggregationByExample(example, aggregateCondition); Assert.assertEquals(2, m.size()); Assert.assertEquals(new Long(6), m.get(0).getAggregation()); Assert.assertEquals(new Long(3), m.get(1).getAggregation()); } finally { sqlSession.close(); } } @Test public void testMin() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); AggregateCondition aggregateCondition = AggregateCondition.builder(). aggregateBy("id").aliasName("aggregation").aggregateType(AggregateType.MIN); Example example = new Example(User.class); List m = mapper.selectAggregationByExample(example, aggregateCondition); Assert.assertEquals(1, m.size()); Assert.assertEquals(new Long(1), m.get(0).getAggregation()); } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/CreateDB.sql ================================================ drop table user if exists; create table user ( id integer NOT NULL PRIMARY KEY, name varchar(32), role VARCHAR(32) ); INSERT INTO user (id, name, role) VALUES (1, 'Angola', 'Admin'); INSERT INTO user (id, name, role) VALUES (2, 'Afghanistan', 'Admin'); INSERT INTO user (id, name, role) VALUES (3, 'Albania', 'Admin'); INSERT INTO user (id, name, role) VALUES (4, 'Algeria', 'USER'); INSERT INTO user (id, name, role) VALUES (5, 'Andorra', 'USER'); INSERT INTO user (id, name, role) VALUES (6, 'Anguilla', 'USER'); drop table user_hump if exists; create table user_hump ( id integer NOT NULL PRIMARY KEY, user_name varchar(32), user_role VARCHAR(32) ); INSERT INTO user_hump (id, user_name, user_role) VALUES (1, 'Angola', 'Admin'); INSERT INTO user_hump (id, user_name, user_role) VALUES (2, 'Afghanistan', 'Admin'); INSERT INTO user_hump (id, user_name, user_role) VALUES (3, 'Albania', 'Admin'); INSERT INTO user_hump (id, user_name, user_role) VALUES (4, 'Algeria', 'USER'); INSERT INTO user_hump (id, user_name, user_role) VALUES (5, 'Andorra', 'USER'); INSERT INTO user_hump (id, user_name, user_role) VALUES (6, 'Anguilla', 'USER'); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/User.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.aggregation; import jakarta.persistence.Id; import jakarta.persistence.Transient; import java.io.Serializable; /** * @author liuzh */ public class User implements Serializable { private static final long serialVersionUID = 1L; @Id private Long id; private String name; private String role; //存储聚合函数值 @Transient private Long aggregation; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public Long getAggregation() { return aggregation; } public void setAggregation(Long aggregation) { this.aggregation = aggregation; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/UserHump.java ================================================ package tk.mybatis.mapper.additional.aggregation; import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.persistence.Transient; import java.io.Serializable; @Table(name = "user_hump") public class UserHump implements Serializable { private static final long serialVersionUID = 1L; @Id private Long id; private String userName; private String userRole; //存储聚合函数值 @Transient private Long aggregation; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserRole() { return userRole; } public void setUserRole(String userRole) { this.userRole = userRole; } public Long getAggregation() { return aggregation; } public void setAggregation(Long aggregation) { this.aggregation = aggregation; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/UserHumpMapper.java ================================================ package tk.mybatis.mapper.additional.aggregation; import tk.mybatis.mapper.common.Mapper; public interface UserHumpMapper extends Mapper, AggregationMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/UserMapper.java ================================================ package tk.mybatis.mapper.additional.aggregation; public interface UserMapper extends AggregationMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/aggregation/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/delete/Course.java ================================================ package tk.mybatis.mapper.additional.delete; import tk.mybatis.mapper.annotation.LogicDelete; import jakarta.persistence.Column; import jakarta.persistence.Id; import java.time.LocalDate; /** * @author jingkaihui * @date 2019/10/19 */ public class Course { @Id private Integer id; private String name; private Integer price; private LocalDate published; @LogicDelete @Column(name = "is_deleted") private Boolean isDeleted; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public LocalDate getPublished() { return published; } public void setPublished(LocalDate published) { this.published = published; } public Boolean getDeleted() { return isDeleted; } public void setDeleted(Boolean deleted) { isDeleted = deleted; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/delete/CourseMapper.java ================================================ package tk.mybatis.mapper.additional.delete; import tk.mybatis.mapper.common.base.BaseSelectMapper; /** * @author jingkaihui * @date 2019/10/19 */ public interface CourseMapper extends BaseSelectMapper, DeleteByPropertyMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/delete/CreateDB.sql ================================================ drop table course if exists; create table course ( id integer NOT NULL PRIMARY KEY, name varchar(32), price integer, published date, is_deleted integer ); INSERT INTO course VALUES (1, 'JavaStarter1', '50', '2015-11-11', '0'); INSERT INTO course VALUES (2, 'JavaStarter2', '50', '2015-11-11', '0'); INSERT INTO course VALUES (3, 'Java3', '80', '2017-11-11', '0'); INSERT INTO course VALUES (4, 'Java4', '100', '2019-11-11', '0'); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/delete/DeleteByPropertyMapperTest.java ================================================ package tk.mybatis.mapper.additional.delete; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.Arrays; import java.util.List; public class DeleteByPropertyMapperTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } @Test public void deleteByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { CourseMapper mapper = sqlSession.getMapper(CourseMapper.class); Course beforeDelete = mapper.selectByPrimaryKey(2); Assert.assertNotNull(beforeDelete); Assert.assertEquals("JavaStarter2", beforeDelete.getName()); int deletedCount = mapper.deleteByProperty(Course::getName, "JavaStarter2"); Assert.assertEquals(1, deletedCount); Course afterDelete = mapper.selectByPrimaryKey(2); Assert.assertNull(afterDelete); } finally { sqlSession.close(); } } @Test public void deleteInByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { CourseMapper mapper = sqlSession.getMapper(CourseMapper.class); List beforeDelete = mapper.selectAll(); Assert.assertEquals(4, beforeDelete.size()); int deletedCount = mapper.deleteInByProperty(Course::getPrice, Arrays.asList(50, 80, 100)); Assert.assertEquals(4, deletedCount); List afterDelete = mapper.selectAll(); Assert.assertEquals(0, afterDelete.size()); } finally { sqlSession.close(); } } @Test public void deleteBetweenByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { CourseMapper mapper = sqlSession.getMapper(CourseMapper.class); List beforeDelete = mapper.selectAll(); Assert.assertEquals(4, beforeDelete.size()); int deletedCount = mapper.deleteBetweenByProperty(Course::getPrice, 80, 100); Assert.assertEquals(2, deletedCount); List afterDelete = mapper.selectAll(); Assert.assertEquals(2, afterDelete.size()); } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/delete/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/CreateDB.sql ================================================ --该脚本需手动导入本地Oracle库 create table demo_country ( country_id varchar2 (50) constraint pk_demo_country__id primary key, country_name varchar(255) not null, country_code varchar(255) not null ); create sequence seq_demo_country minvalue 1 maxvalue 9999999999 start with 200 increment by 1; INSERT INTO demo_country(country_id, country_name, country_code) VALUES (1, 'Angola', 'AO'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (2, 'Afghanistan', 'AF'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (3, 'Albania', 'AL'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (4, 'Algeria', 'DZ'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (5, 'Andorra', 'AD'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (6, 'Anguilla', 'AI'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (7, 'Antigua and Barbuda', 'AG'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (8, 'Argentina', 'AR'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (9, 'Armenia', 'AM'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (10, 'Australia', 'AU'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (11, 'Austria', 'AT'); INSERT INTO demo_country(country_id, country_name, country_code) VALUES (12, 'Azerbaijan', 'AZ'); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/DemoCountry.java ================================================ package tk.mybatis.mapper.additional.dialect.oracle; import tk.mybatis.mapper.additional.insertlist.UUIdGenId; import tk.mybatis.mapper.annotation.KeySql; import jakarta.persistence.Id; /** * @description: * @author: qrqhuangcy * @date: 2018-11-17 **/ public class DemoCountry { @Id @KeySql(genId = UUIdGenId.class) private String countryId; private String countryName; private String countryCode; public DemoCountry(String countryId, String countryName, String countryCode) { this.countryId = countryId; this.countryName = countryName; this.countryCode = countryCode; } public String getCountryId() { return countryId; } public void setCountryId(String countryId) { this.countryId = countryId; } public String getCountryName() { return countryName; } public void setCountryName(String countryName) { this.countryName = countryName; } public String getCountryCode() { return countryCode; } public void setCountryCode(String countryCode) { this.countryCode = countryCode; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/DemoCountryMapper.java ================================================ package tk.mybatis.mapper.additional.dialect.oracle; import tk.mybatis.mapper.common.base.BaseSelectMapper; /** * @description: * @author: qrqhuangcy * @date: 2018-11-17 **/ public interface DemoCountryMapper extends BaseSelectMapper, OracleMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/OracleTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.dialect.oracle; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * Oracle测试类 */ @Ignore("需要Oracle数据源") public class OracleTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } ; @Override protected void runSql(Reader reader) { } @Test public void testSelect() { SqlSession sqlSession = getSqlSession(); try { DemoCountryMapper mapper = sqlSession.getMapper(DemoCountryMapper.class); List countries = mapper.selectAll(); System.out.println(countries.size()); } finally { sqlSession.close(); } } @Test public void testInsertList() { SqlSession sqlSession = getSqlSession(); try { DemoCountryMapper mapper = sqlSession.getMapper(DemoCountryMapper.class); List countryList = new ArrayList(); countryList.add(new DemoCountry("20", "Zimbabwe", "ZW")); countryList.add(new DemoCountry("21", "Zaire", "ZR")); countryList.add(new DemoCountry("22", "Zambia", "ZM")); int updates = mapper.insertList(countryList); Assert.assertEquals(3, updates); } finally { //sqlSession.commit(); sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/idlist/ABaseMapper.java ================================================ package tk.mybatis.mapper.additional.idlist; /** * @author liuzh */ public interface ABaseMapper extends IdListMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/idlist/CountryMapper.java ================================================ package tk.mybatis.mapper.additional.idlist; import tk.mybatis.mapper.additional.Country; public interface CountryMapper extends ABaseMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/idlist/IdListMapperTest.java ================================================ package tk.mybatis.mapper.additional.idlist; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import tk.mybatis.mapper.additional.Country; import tk.mybatis.mapper.entity.Config; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class IdListMapperTest extends BaseTest { @Override protected Config getConfig() { Config config = super.getConfig(); //安全删除 config.setSafeDelete(true); return config; } /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } @Test public void testByIdList() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List idList = Arrays.asList(1L, 2L, 3L); List countryList = mapper.selectByIdList(idList); Assert.assertEquals(3, countryList.size()); Assert.assertEquals(1L, (long) countryList.get(0).getId()); Assert.assertEquals(2L, (long) countryList.get(1).getId()); Assert.assertEquals(3L, (long) countryList.get(2).getId()); //删除 Assert.assertEquals(3, mapper.deleteByIdList(idList)); //查询结果0 Assert.assertEquals(0, mapper.selectByIdList(idList).size()); } finally { sqlSession.close(); } } @Test(expected = Exception.class) public void testDeleteByEmptyIdList() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); mapper.deleteByIdList(new ArrayList()); } finally { sqlSession.close(); } } @Test public void testSelectByEmptyIdList() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Assert.assertEquals(183, mapper.selectByIdList(new ArrayList()).size()); } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/idlist/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/insertlist/CreateDB.sql ================================================ drop table user if exists; create table user ( id varchar(64) NOT NULL PRIMARY KEY, name varchar(32), role VARCHAR(32) ); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/insertlist/InsertListMapperTest.java ================================================ package tk.mybatis.mapper.additional.insertlist; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.ArrayList; import java.util.List; public class InsertListMapperTest extends BaseTest { private String[][] countries = new String[][]{ {"Angola", "AO"}, {"Afghanistan", "AF"}, {"Albania", "AL"}, {"Algeria", "DZ"}, {"Andorra", "AD"}, {"Anguilla", "AI"}, {"Antigua and Barbuda", "AG"}, {"Argentina", "AR"}, {"Armenia", "AM"}, {"Australia", "AU"}, {"Austria", "AT"}, {"Azerbaijan", "AZ"}, {"Bahamas", "BS"}, {"Bahrain", "BH"}, {"Bangladesh", "BD"}, {"Barbados", "BB"}, {"Belarus", "BY"}, {"Belgium", "BE"}, {"Belize", "BZ"}, {"Benin", "BJ"}, {"Bermuda Is.", "BM"}, {"Bolivia", "BO"}, {"Botswana", "BW"}, {"Brazil", "BR"}, {"Brunei", "BN"}, {"Bulgaria", "BG"}, {"Burkina-faso", "BF"}, {"Burma", "MM"}, {"Burundi", "BI"}, {"Cameroon", "CM"}, {"Canada", "CA"}, {"Central African Republic", "CF"}, {"Chad", "TD"}, {"Chile", "CL"}, {"China", "CN"} }; /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } ; /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } ; @Test public void testInsertList() { SqlSession sqlSession = getSqlSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); List userList = new ArrayList(countries.length); for (int i = 0; i < countries.length; i++) { userList.add(new User(countries[i][0], countries[i][1])); } Assert.assertEquals(countries.length, mapper.insertList(userList)); for (User user : userList) { Assert.assertNotNull(user.getId()); System.out.println(user.getId()); } } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/insertlist/UUIdGenId.java ================================================ package tk.mybatis.mapper.additional.insertlist; import tk.mybatis.mapper.genid.GenId; import java.util.UUID; /** * @author liuzh */ public class UUIdGenId implements GenId { @Override public String genId(String table, String column) { return UUID.randomUUID().toString(); } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/insertlist/User.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.insertlist; import tk.mybatis.mapper.annotation.KeySql; import jakarta.persistence.Id; import java.io.Serializable; /** * @author liuzh */ public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @KeySql(genId = UUIdGenId.class) private String id; private String name; private String role; public User() { } public User(String name, String role) { this.name = name; this.role = role; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/insertlist/UserMapper.java ================================================ package tk.mybatis.mapper.additional.insertlist; import tk.mybatis.mapper.additional.insert.InsertListMapper; public interface UserMapper extends InsertListMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/insertlist/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/select/Book.java ================================================ package tk.mybatis.mapper.additional.select; import jakarta.persistence.Id; import java.time.LocalDate; /** * @author jingkaihui * @date 2019/10/19 */ public class Book { @Id private Integer id; private String name; private Integer price; private LocalDate published; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public LocalDate getPublished() { return published; } public void setPublished(LocalDate published) { this.published = published; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/select/BookMapper.java ================================================ package tk.mybatis.mapper.additional.select; /** * @author jingkaihui * @date 2019/10/19 */ public interface BookMapper extends SelectByPropertyMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/select/CreateDB.sql ================================================ drop table book if exists; create table book ( id integer NOT NULL PRIMARY KEY, name varchar(32), price integer, published date ); INSERT INTO book VALUES (1, 'JavaStarter1', '50', '2015-11-11'); INSERT INTO book VALUES (2, 'JavaStarter2', '50', '2015-11-11'); INSERT INTO book VALUES (3, 'Java3', '80', '2017-11-11'); INSERT INTO book VALUES (4, 'Java4', '100', '2019-11-11'); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/select/SelectByPropertyMapperTest.java ================================================ package tk.mybatis.mapper.additional.select; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.time.LocalDate; import java.util.Arrays; import java.util.List; public class SelectByPropertyMapperTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } @Test public void selectOneByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { BookMapper mapper = sqlSession.getMapper(BookMapper.class); Book book = mapper.selectOneByProperty(Book::getName, "JavaStarter1"); Assert.assertNotNull(book); Assert.assertEquals("JavaStarter1", book.getName()); } finally { sqlSession.close(); } } @Test public void selectByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { BookMapper mapper = sqlSession.getMapper(BookMapper.class); List books = mapper.selectByProperty(Book::getPrice, 50); Assert.assertEquals(2, books.size()); } finally { sqlSession.close(); } } @Test public void selectInByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { BookMapper mapper = sqlSession.getMapper(BookMapper.class); List books = mapper.selectInByProperty(Book::getPrice, Arrays.asList(50, 80)); Assert.assertEquals(3, books.size()); } finally { sqlSession.close(); } } @Test public void selectBetweenByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { BookMapper mapper = sqlSession.getMapper(BookMapper.class); List books = mapper.selectBetweenByProperty(Book::getPublished, LocalDate.of(2015, 11, 11), LocalDate.of(2019, 11, 11)); Assert.assertEquals(4, books.size()); } finally { sqlSession.close(); } } @Test public void selectCountByPropertyTest() { SqlSession sqlSession = getSqlSession(); try { BookMapper mapper = sqlSession.getMapper(BookMapper.class); int count = mapper.selectCountByProperty(Book::getPrice, 50); Assert.assertEquals(2, count); } finally { sqlSession.close(); } } @Test public void existsWithPropertyTest() { SqlSession sqlSession = getSqlSession(); try { BookMapper mapper = sqlSession.getMapper(BookMapper.class); boolean exist = mapper.existsWithProperty(Book::getPrice, 50); Assert.assertTrue(exist); } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/select/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/differ/CountryMapper.java ================================================ package tk.mybatis.mapper.additional.update.differ; import org.apache.ibatis.annotations.Select; import tk.mybatis.mapper.additional.Country; public interface CountryMapper extends UpdateByDifferMapper { @Select("select * from country where id = #{id}") Country selectByPrimaryKey(Long id); } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/differ/UpdateByDifferMapperTest.java ================================================ package tk.mybatis.mapper.additional.update.differ; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import tk.mybatis.mapper.additional.Country; import java.io.IOException; import java.io.Reader; import java.net.URL; public class UpdateByDifferMapperTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } ; @Test public void testUpdateByDiffer() { SqlSession sqlSession = getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country old = mapper.selectByPrimaryKey(1L); //(1, 'Angola', 'AO', 1) Country newer = new Country(); newer.setId(1L); newer.setCountryname("Newer"); newer.setCountrycode("AO"); int count = mapper.updateByDiffer(old, newer); Assert.assertEquals(1, count); old = mapper.selectByPrimaryKey(1L); Assert.assertEquals(1L, old.getId().longValue()); Assert.assertEquals("Newer", old.getCountryname()); Assert.assertEquals("AO", old.getCountrycode()); } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/differ/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/force/CountryInt.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.update.force; import jakarta.persistence.Id; import java.io.Serializable; /** * @author qrqhuangcy * @Description: 验证数值空值强制更新 * @date 2018-06-25 */ public class CountryInt implements Serializable { private static final long serialVersionUID = -1626761012846137805L; @Id private Integer id; private String countryname; private Integer countrycode; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getCountrycode() { return countrycode; } public void setCountrycode(Integer countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/force/CountryIntMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.update.force; import tk.mybatis.mapper.common.base.BaseSelectMapper; /** * @author qrqhuangcy * @Description: 验证数值空值强制更新 * @date 2018-06-25 */ public interface CountryIntMapper extends BaseSelectMapper, UpdateByPrimaryKeySelectiveForceMapper { } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/force/CreateDB.sql ================================================ drop table country_int if exists; create table country_int ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode integer ); INSERT INTO country_int (id, countryname, countrycode) VALUES (174, 'United States of America', 100); ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/force/UpdateByPrimaryKeySelectiveForceTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.update.force; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.additional.BaseTest; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.Arrays; /** * @author qrqhuangcy * @Description: 验证数值空值强制更新 * @date 2018-06-25 */ public class UpdateByPrimaryKeySelectiveForceTest extends BaseTest { /** * 获取 mybatis 配置 * * @return */ protected Reader getConfigFileAsReader() throws IOException { URL url = getClass().getResource("mybatis-config.xml"); return toReader(url); } ; /** * 获取初始化 sql * * @return */ protected Reader getSqlFileAsReader() throws IOException { URL url = getClass().getResource("CreateDB.sql"); return toReader(url); } @Test public void testUpdateByPrimaryKeySelectiveForceByNull() { SqlSession sqlSession = getSqlSession(); try { CountryIntMapper mapper = sqlSession.getMapper(CountryIntMapper.class); CountryInt country = new CountryInt(); country.setId(174); country.setCountryname("英国"); mapper.updateByPrimaryKeySelectiveForce(country, null); country = mapper.selectByPrimaryKey(174); Assert.assertNotNull(country.getCountrycode()); } finally { sqlSession.close(); } } @Test public void testUpdateByPrimaryKeySelectiveForce() { SqlSession sqlSession = getSqlSession(); try { CountryIntMapper mapper = sqlSession.getMapper(CountryIntMapper.class); CountryInt country = new CountryInt(); country.setId(174); mapper.updateByPrimaryKeySelectiveForce(country, Arrays.asList("countrycode", "countryname")); country = mapper.selectByPrimaryKey(174); Assert.assertNull(country.getCountrycode()); Assert.assertNull(country.getCountryname()); } finally { sqlSession.close(); } } } ================================================ FILE: extra/src/test/java/tk/mybatis/mapper/additional/update/force/mybatis-config.xml ================================================ ================================================ FILE: extra/src/test/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: generator/README.md ================================================ # Mybatis 通用 Mapper 代码生成器 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-generator/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-generator) 整个插件只有很少代码是和通用 Mapper 相关的,并且也没有直接的依赖关系。 这个代码生成器实际上是对 MyBatis Generator 的一个扩展,使用这个扩展可以很方便的使用 Freemarker 模板语言编写代码。 ## 测试 在 src/test/java 下面,`tk.mybatis.mapper.generator` 包下面有一个测试类 `Generator`。 可以直接运行这个测试类查看生成代码的效果。所有生成的代码在 `src/test/java/test` 目录下,方便删除。 测试使用的 hsqldb 内存数据库,数据库建表 SQL 在 src/test/resources 下面的 `CreateDB.sql` 中。 代码生成器的配置在 `generatorConfig.xml` 中。 # 代码生成器文档 代码生成器是基于 MBG 插件的,所以需要配合 MBG 使用。 一个简单的 MBG 配置如下: ```xml
``` 在这个配置中,我们只关注 `tk.mybatis.mapper.generator.TemplateFilePlugin`。 ## 基于模板的插件 `TemplateFilePlugin` 这个插件中除了几个必备的属性外,还可以增加任意的属性,属性完全是为了给模板提供数据。 先看一个基本完整的配置: ```xml ``` 下面介绍必备的属性。 ### 1. `targetProject` 用于指定目标项目,一般是 `src/main/java` 或者 `src/main/resource` 这样的目录。 还可以是 `src/test/java` 或者 `src/test/resource` 这样的目录。 在多模块项目中,还能通过相对路径指定为其他的目录,例如: ```xml ``` **这个属性值有一个要求,就是目录必须存在,否则不会生成代码!** ### 2. `targetPackage` 用于指定包的部分,虽然是这个名字,实际上就是路径。 **这个属性指定的路径如果不存在,就会自动创建。** 这个属性的值可以为空。 例如 `mapper/admin` 用于生成 `mapper/admin/` 目录,或者 `tk.mybatis.mapper` 生成包(本质上还是目录)。 这个属性还有一个特殊的地方,它还支持使用模板,就和下面的 `fileName` 一样,举个简单的使用场景。 > 你可能在生成前端代码的时候,希望将表对应的 JSP 生成在自己的一个目录中,此时可以配置为: > >`` > >模板中可以用到的属性,这里都能用,其他属性后面会介绍。 通过这个路径也能看出来,配置一个插件只能根据模板在一个指定位置(targetProject 和 targetPackage 决定的目录)生成一个文件。 ### 3. `templatePath` 指定模板路径,可以是任意能够通过 ClassLoader 能够获取的位置,文件类型没有限制。 例如示例中的 `generator/test-one.ftl`。 **这个属性必须指定,否则不会生成代码!** ### 4. `fileName` 这个属性用于指定生成文件的名字,这个值支持使用模板,例如上面的 `${tableClass.shortClassName}Test.txt`,具体可用的属性会在后面介绍。 **这个属性必须指定,否则不会生成代码!** ### 5. `templateFormatter` **这个属性可选,默认使用基于 FreeMarker 的实现!** 默认情况下,你需要添加下面的依赖: ```xml org.freemarker freemarker 2.3.23 ``` 默认的实现类为:`tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter`。 这个类实现了两个接口 `TemplateFormatter, ListTemplateFormatter`。 这俩接口分别对应下面 `singleMode` 参数值的 `true` 和 `false`。 也就是一个表生成一个文件,或者多个表生成一个文件。 对于一般情况下,都是第一种情况。但是在配置文件中,可能会用到多个表的信息。 如果你想使用其他模板引擎,可以自己实现上面的接口。 ### 6. `singleMode` 上面已经提过,默认为 `true`。 一个表生成一个文件时,可用属性可以参考 `generator/test-one.ftl`,表的属性在 `tableClass` 中。 多个表生成一个文件时,可用属性可以参考 `generator/test-all.ftl`,所有表的属性在 `tableClassSet` 中,通过遍历可以获取单个的信息。 ### 7. 其他你需要的属性 模板中需要的特殊信息都可以通过 `` 方法设置,在模板中直接使用这里定义的属性名来使用,后面例子的中的 `mapperSuffix` 就是这种属性。 ## `TemplateFilePlugin` 配置示例 因为模板需要根据业务进行设计,所以这里只提供了两个简单的 mapper 目标和两个完整属性的示例模板。 因为一个模板只能生成一类的文件,所以如果要生成多个不同的文件,就需要配置多个插件。 > 这种设计很灵活,因为自由度很高,所以代价就是配置的多。 > >但是正常情况下,根据业务设计的一套模板基本是固定的,不会有太多变化,所以用起来并不麻烦。 例如下面的示例: ```xml ``` 前两个会生成 Dao 后缀的 Mapper 接口和 XML,其中有个针对性的参数 `mapperSuffix` 用于配置后缀, 还有个 `mapperPackage` 在生成 XML 时获取接口的包名(因为和这里的 `targetPackage` 可以不同)。 后两个插件用于演示所有可用的属性,而且是两种不同的模式。 在表和实体上可用的所有属性如下: ``` 特殊:targetPackage值在 ${package} 中。 当前时间: <#assign dateTime = .now> 日期:${dateTime?date} 时间:${dateTime?time} 格式化:${dateTime?string["yyyy-MM-dd HH:mm:ss"]} 所有配置的属性信息: <#list props?keys as key> ${key} - ${props[key]} 实体和表的信息: 表名:${tableClass.tableName} 表注释:${tableClass.remarks} 变量名:${tableClass.variableName} 小写名:${tableClass.lowerCaseName} 类名:${tableClass.shortClassName} 全名:${tableClass.fullClassName} 包名:${tableClass.packageName} 列的信息: ===================================== <#if tableClass.pkFields??> 主键: <#list tableClass.pkFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} <#if tableClass.baseFields??> 基础列: <#list tableClass.baseFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} <#if tableClass.blobFields??> Blob列: <#list tableClass.blobFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} ===================================== 全部列(包含了pk,base,blob 字段,可用的属性和上面的一样): <#if tableClass.allFields??> 列名 - 字段名 <#list tableClass.allFields as field> ${field.columnName} - ${field.fieldName} ``` ## 测试执行 上面示例就是本项目的测试代码,在 `src/test/resources/generator/generatorConfig.xml` 中。 还提供了一种 Java 编码方式运行的类,`src/test/java/` 中的 `tk.mybatis.mapper.generator.Generator`,配置上面 xml 中的数据库信息就可以生成。 测试生成的**部分**结果如下。 实体: ```java @Table(name = "`user_info`") public class UserInfo { @Id @Column(name = "`Id`") @GeneratedValue(generator = "JDBC") private Integer id; ``` Dao: ```java package test.mapper; import test.model.UserInfo; /** * 通用 Mapper 代码生成器 * * @author mapper-generator */ public interface UserInfoDao extends tk.mybatis.mapper.common.Mapper { } ``` XML: ```xml ``` test-one.ftl 生成的信息如下: ```java 目标package: 当前时间: 2017-11-6 22:00:45 2017-11-06 22:00:45 所有配置的属性信息: targetPackage - templateFormatter - tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter templatePath - generator/test-one.ftl targetProject - src/test/resources fileName - ${tableClass.shortClassName}Test.txt 实体和表的信息: 表名:user_info 表注释:用户信息表 变量名:userInfo 小写名:userinfo 类名:UserInfo 全名:test.model.UserInfo 包名:test.model 列的信息: ===================================== 主键: ------------------------------------- 列名:Id 列类型:INTEGER 字段名:id 注释: 类型包名:java.lang 类型短名:Integer 类型全名:java.lang.Integer 是否主键:true 是否可空:false 是否为BLOB列:false 是否为String列:false 是否为字符串列:false 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:10 列精度:0 基础列: ------------------------------------- 列名:username 列类型:VARCHAR 字段名:username 注释:用户名 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:false 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:32 列精度:0 ------------------------------------- 列名:password 列类型:VARCHAR 字段名:password 注释:密码 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:32 列精度:0 ------------------------------------- 列名:usertype 列类型:VARCHAR 字段名:usertype 注释:用户类型 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:2 列精度:0 ------------------------------------- 列名:enabled 列类型:INTEGER 字段名:enabled 注释:是否可用 类型包名:java.lang 类型短名:Integer 类型全名:java.lang.Integer 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:false 是否为字符串列:false 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:10 列精度:0 ------------------------------------- 列名:realname 列类型:VARCHAR 字段名:realname 注释:真实姓名 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:32 列精度:0 ------------------------------------- 列名:qq 列类型:VARCHAR 字段名:qq 注释:QQ 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:14 列精度:0 ------------------------------------- 列名:email 列类型:VARCHAR 字段名:email 注释: 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:100 列精度:0 ------------------------------------- 列名:tel 列类型:VARCHAR 字段名:tel 注释:联系电话 类型包名:java.lang 类型短名:String 类型全名:java.lang.String 是否主键:false 是否可空:true 是否为BLOB列:false 是否为String列:true 是否为字符串列:true 是否为日期列:false 是否为时间列:false 是否为序列列:false 列长度:255 列精度:0 Blob列: ===================================== 全部列: 列名 - 字段名 Id - id username - username password - password usertype - usertype enabled - enabled realname - realname qq - qq email - email tel - tel ``` ## 最后 基础的代码生成器是很简单的,和 Java 拼字符串输出很像,这里只是使用了模板。 几乎所有人都在 JSP 中用过的 EL 就是一种模板,可能你会 ` 项目的发展离不开你的支持,请作者喝杯咖啡吧! > >支付宝 > >支付宝 > >微信 > >微信 ================================================ FILE: generator/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-generator jar mapper-generator Mybatis 通用 Mapper 代码生成器 2.3.33 1.4.2 org.freemarker freemarker ${freemarker.version} provided org.mybatis.generator mybatis-generator-core ${generator.version} provided org.projectlombok lombok 1.18.34 provided io.swagger swagger-annotations 1.6.14 provided org.hsqldb sqltool 2.5.2 test jakarta.persistence jakarta.persistence-api test tk.mybatis mapper-base ${project.version} test ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/FalseMethodPlugin.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.Interface; import org.mybatis.generator.api.dom.java.Method; import org.mybatis.generator.api.dom.java.TopLevelClass; import org.mybatis.generator.api.dom.xml.XmlElement; import java.util.List; /** * 禁用大多数方法 * * @author liuzh */ public class FalseMethodPlugin extends PluginAdapter { @Override public boolean validate(List warnings) { return true; } //下面所有return false的方法都不生成。这些都是基础的CRUD方法,使用通用Mapper实现 @Override public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientSelectAllMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapInsertSelectiveElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapSelectAllElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapSelectByPrimaryKeyElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapUpdateByPrimaryKeySelectiveElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { return false; } @Override public boolean providerGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { return false; } @Override public boolean providerApplyWhereMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { return false; } @Override public boolean providerInsertSelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { return false; } @Override public boolean providerUpdateByPrimaryKeySelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { return false; } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/MapperCommentGenerator.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.mybatis.generator.api.CommentGenerator; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.TextElement; import org.mybatis.generator.api.dom.xml.XmlElement; import org.mybatis.generator.config.MergeConstants; import org.mybatis.generator.internal.util.StringUtility; import java.text.MessageFormat; import java.util.Properties; import java.util.Set; public class MapperCommentGenerator implements CommentGenerator { //开始的分隔符,例如mysql为`,sqlserver为[ private String beginningDelimiter = ""; //结束的分隔符,例如mysql为`,sqlserver为] private String endingDelimiter = ""; //强制生成注解 private boolean forceAnnotation; //强制不生成注解 private boolean forceNonAnnotation; //是否生成swagger注解 private boolean needsSwagger; //逻辑删除字段 private String logicDeleteColumn = ""; public MapperCommentGenerator() { super(); } @Override public void addJavaFileComment(CompilationUnit compilationUnit) { return; } /** * xml中的注释 * * @param xmlElement */ @Override public void addComment(XmlElement xmlElement) { xmlElement.addElement(new TextElement("")); } @Override public void addRootComment(XmlElement rootElement) { return; } @Override public void addConfigurationProperties(Properties properties) { String beginningDelimiter = properties.getProperty("beginningDelimiter"); if (StringUtility.stringHasValue(beginningDelimiter)) { this.beginningDelimiter = beginningDelimiter; } String endingDelimiter = properties.getProperty("endingDelimiter"); if (StringUtility.stringHasValue(endingDelimiter)) { this.endingDelimiter = endingDelimiter; } String forceAnnotation = properties.getProperty("forceAnnotation"); if (StringUtility.stringHasValue(forceAnnotation)) { this.forceAnnotation = "TRUE".equalsIgnoreCase(forceAnnotation); } String forceNonAnnotation = properties.getProperty("forceNonAnnotation"); if (StringUtility.stringHasValue(forceNonAnnotation)) { this.forceNonAnnotation = "TRUE".equalsIgnoreCase(forceNonAnnotation); } String needsSwagger = properties.getProperty("needsSwagger"); if (StringUtility.stringHasValue(needsSwagger)) { this.needsSwagger = "TRUE".equalsIgnoreCase(needsSwagger); } String logicDeleteColumn = properties.getProperty("logicDeleteColumn"); if (StringUtility.stringHasValue(logicDeleteColumn)) { this.logicDeleteColumn = logicDeleteColumn; } } public String getDelimiterName(String name) { StringBuilder nameBuilder = new StringBuilder(); nameBuilder.append(beginningDelimiter); nameBuilder.append(name); nameBuilder.append(endingDelimiter); return nameBuilder.toString(); } /** * 删除标记 * * @param javaElement * @param markAsDoNotDelete */ protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append(MergeConstants.NEW_ELEMENT_TAG); if (markAsDoNotDelete) { sb.append(" do_not_delete_during_merge"); } javaElement.addJavaDocLine(sb.toString()); } /** * Example使用 * * @param innerClass * @param introspectedTable */ @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { } @Override public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { } /** * 给字段添加数据库备注 * * @param field * @param introspectedTable * @param introspectedColumn */ @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) { field.addJavaDocLine("/**"); StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append(introspectedColumn.getRemarks()); field.addJavaDocLine(sb.toString()); field.addJavaDocLine(" */"); } //添加注解 if (field.isTransient()) { //@Column field.addAnnotation("@Transient"); } for (IntrospectedColumn column : introspectedTable.getPrimaryKeyColumns()) { if (introspectedColumn == column) { field.addAnnotation("@Id"); break; } } String column = introspectedColumn.getActualColumnName(); if (StringUtility.stringContainsSpace(column) || introspectedTable.getTableConfiguration().isAllColumnDelimitingEnabled()) { column = introspectedColumn.getContext().getBeginningDelimiter() + column + introspectedColumn.getContext().getEndingDelimiter(); } if (!forceNonAnnotation) { if (!column.equals(introspectedColumn.getJavaProperty())) { //@Column field.addAnnotation("@Column(name = \"" + getDelimiterName(column) + "\")"); } else if (StringUtility.stringHasValue(beginningDelimiter) || StringUtility.stringHasValue(endingDelimiter)) { field.addAnnotation("@Column(name = \"" + getDelimiterName(column) + "\")"); } else if (forceAnnotation) { field.addAnnotation("@Column(name = \"" + getDelimiterName(column) + "\")"); } } // 添加逻辑删除注解 if (column.equals(this.logicDeleteColumn)) { field.addAnnotation("@LogicDelete"); } if (introspectedColumn.isIdentity()) { if ("JDBC".equals(introspectedTable.getTableConfiguration().getGeneratedKey().get().getRuntimeSqlStatement())) { field.addAnnotation("@GeneratedValue(generator = \"JDBC\")"); } else { field.addAnnotation("@GeneratedValue(strategy = GenerationType.IDENTITY)"); } } else if (introspectedColumn.isSequenceColumn()) { //在 Oracle 中,如果需要是 SEQ_TABLENAME,那么可以配置为 select SEQ_{1} from dual String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime(); String sql = MessageFormat.format(introspectedTable.getTableConfiguration().getGeneratedKey().get().getRuntimeSqlStatement(), tableName, tableName.toUpperCase()); field.addAnnotation("@GeneratedValue(strategy = GenerationType.IDENTITY, generator = \"" + sql + "\")"); } // region swagger注解 if (this.needsSwagger) { String remarks = introspectedColumn.getRemarks(); if (remarks == null) { remarks = ""; } String swaggerAnnotation = "@ApiModelProperty(value = \"%s\" da )"; field.addAnnotation("@ApiModelProperty(\"" + remarks.replaceAll("\r", "").replaceAll("\n", "") + "\")"); } // endregion } /** * Example使用 * * @param field * @param introspectedTable */ @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable) { } @Override public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { } /** * @param method * @param introspectedTable */ @Override public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { } /** * getter方法注释 * * @param method * @param introspectedTable * @param introspectedColumn */ @Override public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { StringBuilder sb = new StringBuilder(); method.addJavaDocLine("/**"); if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) { sb.append(" * 获取"); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" *"); } sb.setLength(0); sb.append(" * @return "); sb.append(introspectedColumn.getJavaProperty()); if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) { sb.append(" - "); sb.append(introspectedColumn.getRemarks()); } method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" */"); } /** * setter方法注释 * * @param method * @param introspectedTable * @param introspectedColumn */ @Override public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { StringBuilder sb = new StringBuilder(); method.addJavaDocLine("/**"); if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) { sb.append(" * 设置"); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" *"); } Parameter parm = method.getParameters().get(0); sb.setLength(0); sb.append(" * @param "); sb.append(parm.getName()); if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) { sb.append(" "); sb.append(introspectedColumn.getRemarks()); } method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" */"); } /** * Example使用 * * @param innerClass * @param introspectedTable * @param markAsDoNotDelete */ @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { } /** * @since mbg 1.3.6 */ @Override public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, Set set) { } /** * @since mbg 1.3.6 */ @Override public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set set) { } /** * @since mbg 1.3.6 */ @Override public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, Set set) { } /** * @since mbg 1.3.6 */ @Override public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set set) { } /** * @since mbg 1.3.6 */ @Override public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable, Set set) { } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/MapperPlugin.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.config.CommentGeneratorConfiguration; import org.mybatis.generator.config.Context; import org.mybatis.generator.config.JDBCConnectionConfiguration; import org.mybatis.generator.internal.util.StringUtility; import java.util.*; /** * 通用Mapper生成器插件 * * @author liuzh */ public class MapperPlugin extends FalseMethodPlugin { private Set mappers = new HashSet(); private boolean caseSensitive = false; private boolean useMapperCommentGenerator = true; //开始的分隔符,例如mysql为`,sqlserver为[ private String beginningDelimiter = ""; //结束的分隔符,例如mysql为`,sqlserver为] private String endingDelimiter = ""; //数据库模式 private String schema; //注释生成器 private CommentGeneratorConfiguration commentCfg; //强制生成注解 private boolean forceAnnotation; //强制不生成注解 private boolean forceNonAnnotation; //是否需要生成Data注解 private boolean needsData = false; //是否需要生成Getter注解 private boolean needsGetter = false; //是否需要生成Setter注解 private boolean needsSetter = false; //是否需要生成ToString注解 private boolean needsToString = false; //是否需要生成Accessors(chain = true)注解 private boolean needsAccessors = false; private boolean needsBuilder = false; private boolean needsSuperBuilder = false; private boolean needsNoArgsConstructor = false; private boolean needsAllArgsConstructor = false; //是否需要生成EqualsAndHashCode注解 private boolean needsEqualsAndHashCode = false; //是否需要生成EqualsAndHashCode注解,并且“callSuper = true” private boolean needsEqualsAndHashCodeAndCallSuper = false; //是否生成字段名常量 private boolean generateColumnConsts = false; //是否生成默认的属性的静态方法 private boolean generateDefaultInstanceMethod = false; //是否生成swagger注解,包括 @ApiModel和@ApiModelProperty private boolean needsSwagger = false; //是否逻辑删除 private boolean logicDelete = false; public String getDelimiterName(String name) { StringBuilder nameBuilder = new StringBuilder(); if (StringUtility.stringHasValue(schema)) { nameBuilder.append(schema); nameBuilder.append("."); } nameBuilder.append(beginningDelimiter); nameBuilder.append(name); nameBuilder.append(endingDelimiter); return nameBuilder.toString(); } /** * 生成的Mapper接口 * * @param interfaze * @param introspectedTable * @return */ @Override public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) { //获取实体类 FullyQualifiedJavaType entityType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()); //import接口 for (String mapper : mappers) { interfaze.addImportedType(new FullyQualifiedJavaType(mapper)); interfaze.addSuperInterface(new FullyQualifiedJavaType(mapper + "<" + entityType.getShortName() + ">")); } //import实体类 interfaze.addImportedType(entityType); return true; } /** * 处理实体类的包和@Table注解 * * @param topLevelClass * @param introspectedTable */ private void processEntityClass(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { //引入JPA注解 topLevelClass.addImportedType("jakarta.persistence.*"); //lombok扩展开始 //如果需要Data,引入包,代码增加注解 if (this.needsData) { topLevelClass.addImportedType("lombok.Data"); topLevelClass.addAnnotation("@Data"); } //如果需要Getter,引入包,代码增加注解 if (this.needsGetter) { topLevelClass.addImportedType("lombok.Getter"); topLevelClass.addAnnotation("@Getter"); } //如果需要Setter,引入包,代码增加注解 if (this.needsSetter) { topLevelClass.addImportedType("lombok.Setter"); topLevelClass.addAnnotation("@Setter"); } //如果需要ToString,引入包,代码增加注解 if (this.needsToString) { topLevelClass.addImportedType("lombok.ToString"); topLevelClass.addAnnotation("@ToString"); } // 如果需要EqualsAndHashCode,并且“callSuper = true”,引入包,代码增加注解 if (this.needsEqualsAndHashCodeAndCallSuper) { topLevelClass.addImportedType("lombok.EqualsAndHashCode"); topLevelClass.addAnnotation("@EqualsAndHashCode(callSuper = true)"); } else { // 如果需要EqualsAndHashCode,引入包,代码增加注解 if (this.needsEqualsAndHashCode) { topLevelClass.addImportedType("lombok.EqualsAndHashCode"); topLevelClass.addAnnotation("@EqualsAndHashCode"); } } // 如果需要Accessors,引入包,代码增加注解 if (this.needsAccessors) { topLevelClass.addImportedType("lombok.experimental.Accessors"); topLevelClass.addAnnotation("@Accessors(chain = true)"); } if (this.needsSuperBuilder) { topLevelClass.addImportedType("lombok.experimental.SuperBuilder"); topLevelClass.addAnnotation("@SuperBuilder"); } if (this.needsBuilder) { topLevelClass.addImportedType("lombok.Builder"); topLevelClass.addAnnotation("@Builder"); } if (this.needsNoArgsConstructor) { topLevelClass.addImportedType("lombok.NoArgsConstructor"); topLevelClass.addAnnotation("@NoArgsConstructor"); } if (this.needsAllArgsConstructor) { topLevelClass.addImportedType("lombok.AllArgsConstructor"); topLevelClass.addAnnotation("@AllArgsConstructor"); } // lombok扩展结束 // region swagger扩展 if (this.needsSwagger) { //导包 topLevelClass.addImportedType("io.swagger.annotations.ApiModel"); topLevelClass.addImportedType("io.swagger.annotations.ApiModelProperty"); //增加注解(去除注释中的转换符) String remarks = introspectedTable.getRemarks(); if (remarks == null) { remarks = ""; } topLevelClass.addAnnotation("@ApiModel(\"" + remarks.replaceAll("\r", "").replaceAll("\n", "") + "\")"); } // endregion swagger扩展 String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime(); //region 文档注释 String remarks = introspectedTable.getRemarks(); topLevelClass.addJavaDocLine("/**"); topLevelClass.addJavaDocLine(" * 表名:" + tableName); if (remarks != null) { remarks = remarks.trim(); } if (remarks != null && remarks.trim().length() > 0) { String[] lines = remarks.split("\\r?\\n"); for (int i = 0; i < lines.length; i++) { String line = lines[i]; if (i == 0) { topLevelClass.addJavaDocLine(" * 表注释:" + line); } else { topLevelClass.addJavaDocLine(" * " + line); } } } topLevelClass.addJavaDocLine("*/"); //endregion //如果包含空格,或者需要分隔符,需要完善 if (StringUtility.stringContainsSpace(tableName)) { tableName = context.getBeginningDelimiter() + tableName + context.getEndingDelimiter(); } //是否忽略大小写,对于区分大小写的数据库,会有用 if (!forceNonAnnotation) { if (caseSensitive && !topLevelClass.getType().getShortName().equals(tableName)) { topLevelClass.addAnnotation("@Table(name = \"" + getDelimiterName(tableName) + "\")"); } else if (!topLevelClass.getType().getShortName().equalsIgnoreCase(tableName)) { topLevelClass.addAnnotation("@Table(name = \"" + getDelimiterName(tableName) + "\")"); } else if (StringUtility.stringHasValue(schema) || StringUtility.stringHasValue(beginningDelimiter) || StringUtility.stringHasValue(endingDelimiter)) { topLevelClass.addAnnotation("@Table(name = \"" + getDelimiterName(tableName) + "\")"); } else if (forceAnnotation) { topLevelClass.addAnnotation("@Table(name = \"" + getDelimiterName(tableName) + "\")"); } } if (generateColumnConsts) { for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) { String fieldName = introspectedColumn.getActualColumnName().toUpperCase(); //$NON-NLS-1$ FullyQualifiedJavaType fieldType = new FullyQualifiedJavaType(String.class.getName()); //$NON-NLS-1$ Field field = new Field(fieldName, fieldType); field.setVisibility(JavaVisibility.PUBLIC); field.setStatic(true); field.setFinal(true); field.setInitializationString("\"" + introspectedColumn.getJavaProperty() + "\""); context.getCommentGenerator().addFieldComment(field, introspectedTable, introspectedColumn); topLevelClass.addField(field); //增加字段名常量,用于pageHelper String columnFieldName = "DB_" + introspectedColumn.getActualColumnName().toUpperCase(); //$NON-NLS-1$ FullyQualifiedJavaType columnFieldType = new FullyQualifiedJavaType(String.class.getName()); //$NON-NLS-1$ Field columnField = new Field(columnFieldName, columnFieldType); columnField.setVisibility(JavaVisibility.PUBLIC); columnField.setStatic(true); columnField.setFinal(true); columnField.setInitializationString("\"" + introspectedColumn.getActualColumnName() + "\""); topLevelClass.addField(columnField); } } if(this.logicDelete) { topLevelClass.addImportedType("tk.mybatis.mapper.annotation.LogicDelete"); } if (generateDefaultInstanceMethod) { //注意基本类型和包装的index要一致,方便后面使用 List baseClassName = Arrays.asList("byte", "short", "char", "int", "long", "float", "double", "boolean"); List wrapperClassName = Arrays.asList("Byte", "Short", "Character", "Integer", "Long", "Float", "Double", "Boolean"); List otherClassName = Arrays.asList("String", "BigDecimal", "BigInteger"); Method defaultMethod = new Method("defaultInstance"); //增加方法注释 defaultMethod.addJavaDocLine("/**"); defaultMethod.addJavaDocLine(" * 带默认值的实例"); defaultMethod.addJavaDocLine("*/"); defaultMethod.setStatic(true); defaultMethod.setVisibility(JavaVisibility.PUBLIC); defaultMethod.setReturnType(topLevelClass.getType()); defaultMethod.addBodyLine(String.format("%s instance = new %s();", topLevelClass.getType().getShortName(), topLevelClass.getType().getShortName())); for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) { String shortName = introspectedColumn.getFullyQualifiedJavaType().getShortName(); if (!baseClassName.contains(shortName) && !wrapperClassName.contains(shortName) && !otherClassName.contains(shortName)) { continue; } if (introspectedColumn.getDefaultValue() != null) { String defaultValue = introspectedColumn.getDefaultValue(); //处理备注中带有类型描述情况,如 postgresql中存在 ''::character varying if (defaultValue.matches("'\\.*'::\\w+(\\s\\w+)?")) { // defaultValue = defaultValue.substring(0, defaultValue.lastIndexOf("::")); } //去除前后'',如 '123456' -> 123456 if (defaultValue.startsWith("'") && defaultValue.endsWith("'")) { if (defaultValue.length() == 2) { defaultValue = ""; } else { defaultValue = defaultValue.substring(1, defaultValue.length() - 1); } } //暂不支持时间类型默认值识别,不同数据库表达式不同 if ("Boolean".equals(shortName) || "boolean".equals(shortName)) { if ("0".equals(defaultValue)) { defaultValue = "false"; } else if ("1".equals(defaultValue)) { defaultValue = "true"; } } if ("String".equals(shortName)) { //字符串,不通过new String 创建 // 其实通过new String 没有任何问题,不过强迫症,idea会提示,所以改了 defaultMethod.addBodyLine(String.format("instance.%s = \"%s\";", introspectedColumn.getJavaProperty(), defaultValue)); } else { String javaProperty = introspectedColumn.getJavaProperty(); if (baseClassName.contains(shortName)) { //基本类型,转成包装类的new 创建 javaProperty = wrapperClassName.get(baseClassName.indexOf(shortName)); } //通过 new 方法转换 defaultMethod.addBodyLine(String.format("instance.%s = new %s(\"%s\");", javaProperty, shortName, defaultValue)); } } } defaultMethod.addBodyLine("return instance;"); topLevelClass.addMethod(defaultMethod); } } /** * 如果需要生成Getter注解,就不需要生成get相关代码了 */ @Override public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { return !(this.needsData || this.needsGetter); } /** * 如果需要生成Setter注解,就不需要生成set相关代码了 */ @Override public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { return !(this.needsData || this.needsSetter); } /** * 生成基础实体类 * * @param topLevelClass * @param introspectedTable * @return */ @Override public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { processEntityClass(topLevelClass, introspectedTable); return true; } /** * 生成实体类注解KEY对象 * * @param topLevelClass * @param introspectedTable * @return */ @Override public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { processEntityClass(topLevelClass, introspectedTable); return true; } /** * 生成带BLOB字段的对象 * * @param topLevelClass * @param introspectedTable * @return */ @Override public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { processEntityClass(topLevelClass, introspectedTable); return false; } @Override public void setContext(Context context) { super.setContext(context); //设置默认的注释生成器 useMapperCommentGenerator = !"FALSE".equalsIgnoreCase(context.getProperty("useMapperCommentGenerator")); if (useMapperCommentGenerator) { commentCfg = new CommentGeneratorConfiguration(); commentCfg.setConfigurationType(MapperCommentGenerator.class.getName()); context.setCommentGeneratorConfiguration(commentCfg); } JDBCConnectionConfiguration jdbcConnectionConfiguration = null; try { java.lang.reflect.Field jdbcConnectionConfigurationField = Context.class.getDeclaredField("jdbcConnectionConfiguration"); jdbcConnectionConfigurationField.setAccessible(true); jdbcConnectionConfiguration = (JDBCConnectionConfiguration) jdbcConnectionConfigurationField.get(context); } catch (Exception e) { e.printStackTrace(); } //支持oracle获取注释#114 jdbcConnectionConfiguration.addProperty("remarksReporting", "true"); //支持mysql获取注释 jdbcConnectionConfiguration.addProperty("useInformationSchema", "true"); } @Override public void setProperties(Properties properties) { super.setProperties(properties); String mappers = getProperty("mappers"); if (StringUtility.stringHasValue(mappers)) { for (String mapper : mappers.split(",")) { this.mappers.add(mapper); } } else { throw new RuntimeException("Mapper插件缺少必要的mappers属性!"); } this.caseSensitive = Boolean.parseBoolean(this.properties.getProperty("caseSensitive")); this.forceAnnotation = getPropertyAsBoolean("forceAnnotation"); this.forceNonAnnotation = getPropertyAsBoolean("forceNonAnnotation"); this.beginningDelimiter = getProperty("beginningDelimiter", ""); this.endingDelimiter = getProperty("endingDelimiter", ""); this.schema = getProperty("schema"); //lombok扩展 String lombok = getProperty("lombok"); if (lombok != null && !"".equals(lombok)) { this.needsData = lombok.contains("Data"); //@Data 优先级高于 @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode this.needsGetter = !this.needsData && lombok.contains("Getter"); this.needsSetter = !this.needsData && lombok.contains("Setter"); this.needsToString = !this.needsData && lombok.contains("ToString"); this.needsEqualsAndHashCode = !this.needsData && lombok.contains("EqualsAndHashCode"); // 配置lombok扩展EqualsAndHashCode注解是否添加“callSuper = true” String lombokEqualsAndHashCodeCallSuper = getProperty("lombokEqualsAndHashCodeCallSuper", "false"); this.needsEqualsAndHashCodeAndCallSuper = this.needsEqualsAndHashCode && "TRUE".equalsIgnoreCase(lombokEqualsAndHashCodeCallSuper); this.needsAccessors = lombok.contains("Accessors"); this.needsSuperBuilder = lombok.contains("SuperBuilder"); this.needsBuilder = !this.needsSuperBuilder && lombok.contains("Builder"); this.needsNoArgsConstructor = lombok.contains("NoArgsConstructor"); this.needsAllArgsConstructor = lombok.contains("AllArgsConstructor"); } //swagger扩展 String swagger = getProperty("swagger", "false"); if ("TRUE".equalsIgnoreCase(swagger)) { this.needsSwagger = true; } if (useMapperCommentGenerator) { commentCfg.addProperty("beginningDelimiter", this.beginningDelimiter); commentCfg.addProperty("endingDelimiter", this.endingDelimiter); String forceAnnotation = getProperty("forceAnnotation"); if (StringUtility.stringHasValue(forceAnnotation)) { commentCfg.addProperty("forceAnnotation", forceAnnotation); } String forceNonAnnotation = getProperty("forceNonAnnotation"); if (StringUtility.stringHasValue(forceNonAnnotation)) { commentCfg.addProperty("forceNonAnnotation", forceNonAnnotation); } commentCfg.addProperty("needsSwagger", this.needsSwagger + ""); } this.generateColumnConsts = getPropertyAsBoolean("generateColumnConsts"); this.generateDefaultInstanceMethod = getPropertyAsBoolean("generateDefaultInstanceMethod"); this.logicDelete = Boolean.parseBoolean(this.properties.getProperty("logicDelete")); } protected String getProperty(String key) { return this.properties.getProperty(key); } protected String getProperty(String key, String defaultValue) { return this.properties.getProperty(key, defaultValue); } protected Boolean getPropertyAsBoolean(String key) { return Boolean.parseBoolean(getProperty(key)); } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/TemplateFilePlugin.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.mybatis.generator.api.GeneratedJavaFile; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.Field; import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; import org.mybatis.generator.api.dom.java.JavaVisibility; import org.mybatis.generator.internal.ObjectFactory; import org.mybatis.generator.internal.util.StringUtility; import tk.mybatis.mapper.generator.file.GenerateByListTemplateFile; import tk.mybatis.mapper.generator.file.GenerateByTemplateFile; import tk.mybatis.mapper.generator.formatter.ListTemplateFormatter; import tk.mybatis.mapper.generator.formatter.TemplateFormatter; import tk.mybatis.mapper.generator.model.TableClass; import tk.mybatis.mapper.generator.model.TableColumnBuilder; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.*; /** * 每一个模板都需要配置一个插件,可以配置多个 *

*

 * <plugin type="xxx.TemplateFilePlugin">
 *      <property name="targetProject"     value="src/main/java"/>
 *      <property name="targetPackage"     value="com.xxx.controller"/>
 *      <property name="templatePath"      value="template/controller.ftl"/>
 *      <property name="fileName"          value="XXXController.java"/>
 *      <property name="templateFormatter" value="xxx.FreemarkerTemplateFormatter"/>
 * </plugin>
 * 
* * @author liuzh * @since 3.4.5 */ public class TemplateFilePlugin extends PluginAdapter { /** * 默认的模板格式化类 */ public static final String DEFAULT_TEMPLATEFORMATTER = "tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter"; /** * 单个文件模式 */ private String singleMode; /** * 项目路径(目录需要已经存在) */ private String targetProject; /** * 生成的包(路径不存在则创建) */ private String targetPackage; /** * 模板路径 */ private String templatePath; /** * 模板内容 */ private String templateContent; /** * 文件名模板,通过模板方式生成文件名,包含后缀 */ private String fileName; /** * 模板生成器 */ private Object templateFormatter; private String templateFormatterClass; private Set cacheTables; /** * 编码 */ private String encoding; /** * 列转换为字段 * * @param introspectedColumn * @return */ public static Field convertToJavaBeansField(IntrospectedColumn introspectedColumn) { FullyQualifiedJavaType fqjt = introspectedColumn.getFullyQualifiedJavaType(); String property = introspectedColumn.getJavaProperty(); Field field = new Field(property, fqjt); field.setVisibility(JavaVisibility.PRIVATE); return field; } /** * 读取文件 * * @param inputStream * @return * @throws IOException */ protected String read(InputStream inputStream) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding)); StringBuffer stringBuffer = new StringBuffer(); String line = reader.readLine(); while (line != null) { stringBuffer.append(line); line = reader.readLine(); if (line != null) { stringBuffer.append("\n"); } } return stringBuffer.toString(); } @Override public boolean validate(List warnings) { boolean right = true; if (!StringUtility.stringHasValue(fileName)) { warnings.add("没有配置 \"fileName\" 文件名模板,因此不会生成任何额外代码!"); right = false; } if (!StringUtility.stringHasValue(templatePath)) { warnings.add("没有配置 \"templatePath\" 模板路径,因此不会生成任何额外代码!"); right = false; } else { try { URL resourceUrl = null; try { resourceUrl = ObjectFactory.getResource(templatePath); } catch (Exception e) { warnings.add("本地加载\"templatePath\" 模板路径失败,尝试 URL 方式获取!"); } if (resourceUrl == null) { resourceUrl = new URL(templatePath); } InputStream inputStream = resourceUrl.openConnection().getInputStream(); templateContent = read(inputStream); inputStream.close(); } catch (IOException e) { e.printStackTrace(); warnings.add("读取模板文件出错: " + e.getMessage()); right = false; } } if (!StringUtility.stringHasValue(templateFormatterClass)) { templateFormatterClass = DEFAULT_TEMPLATEFORMATTER; warnings.add("没有配置 \"templateFormatterClass\" 模板处理器,使用默认的处理器!"); } try { templateFormatter = Class.forName(templateFormatterClass).newInstance(); } catch (Exception e) { warnings.add("初始化 templateFormatter 出错:" + e.getMessage()); right = false; } if (!right) { return false; } int errorCount = 0; if (!StringUtility.stringHasValue(targetProject)) { errorCount++; warnings.add("没有配置 \"targetProject\" 路径!"); } if (!StringUtility.stringHasValue(targetPackage)) { errorCount++; warnings.add("没有配置 \"targetPackage\" 路径!"); } if (errorCount >= 2) { warnings.add("由于没有配置任何有效路径,不会生成任何额外代码!"); return false; } return true; } @Override public List contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) { List list = new ArrayList(); TableClass tableClass = TableColumnBuilder.build(introspectedTable); if ("TRUE".equalsIgnoreCase(singleMode)) { list.add(new GenerateByTemplateFile(tableClass, (TemplateFormatter) templateFormatter, properties, targetProject, targetPackage, fileName, templateContent)); } else { cacheTables.add(tableClass); } return list; } @Override public List contextGenerateAdditionalJavaFiles() { List list = new ArrayList(); if (cacheTables != null && cacheTables.size() > 0) { list.add(new GenerateByListTemplateFile(cacheTables, (ListTemplateFormatter) templateFormatter, properties, targetProject, targetPackage, fileName, templateContent)); } return list; } @Override public void setProperties(Properties properties) { super.setProperties(properties); this.singleMode = properties.getProperty("singleMode", "true"); if (!"TRUE".equalsIgnoreCase(singleMode)) { this.cacheTables = new LinkedHashSet(); } this.targetProject = properties.getProperty("targetProject"); this.targetPackage = properties.getProperty("targetPackage"); this.templatePath = properties.getProperty("templatePath"); this.fileName = properties.getProperty("fileName"); this.templateFormatterClass = properties.getProperty("templateFormatter"); this.encoding = properties.getProperty("encoding", "UTF-8"); } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/TkMyBatis3Impl.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3Impl; import org.mybatis.generator.internal.util.StringUtility; import java.text.MessageFormat; import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; /** * 可以通过MBG1.3.4+版本提供的table元素的mapperName属性设置统一的名称,使用{0}作为实体类名的占位符。 *

* 用法: *

 * <context id="Mysql" targetRuntime="tk.mybatis.mapper.generator.TkMyBatis3Impl" defaultModelType="flat">
 * </context>
 * 
*

* * @author liuzh * @since 2016-09-04 09:57 */ public class TkMyBatis3Impl extends IntrospectedTableMyBatis3Impl { @Override protected String calculateMyBatis3XmlMapperFileName() { StringBuilder sb = new StringBuilder(); if (stringHasValue(tableConfiguration.getMapperName())) { String mapperName = tableConfiguration.getMapperName(); int ind = mapperName.lastIndexOf('.'); if (ind != -1) { mapperName = mapperName.substring(ind + 1); } //支持mapperName = "{0}Dao" 等用法 sb.append(MessageFormat.format(mapperName, fullyQualifiedTable.getDomainObjectName())); sb.append(".xml"); //$NON-NLS-1$ } else { sb.append(fullyQualifiedTable.getDomainObjectName()); sb.append("Mapper.xml"); //$NON-NLS-1$ } return sb.toString(); } @Override protected void calculateJavaClientAttributes() { if (context.getJavaClientGeneratorConfiguration() == null) { return; } StringBuilder sb = new StringBuilder(); sb.append(this.calculateJavaClientInterfacePackage()); sb.append('.'); if (StringUtility.stringHasValue(this.tableConfiguration.getMapperName())) { //支持mapperName = "{0}Dao" 等用法 sb.append(MessageFormat.format(tableConfiguration.getMapperName(), fullyQualifiedTable.getDomainObjectName())); } else { if (StringUtility.stringHasValue(this.fullyQualifiedTable.getDomainObjectSubPackage())) { sb.append(this.fullyQualifiedTable.getDomainObjectSubPackage()); sb.append('.'); } sb.append(this.fullyQualifiedTable.getDomainObjectName()); sb.append("Mapper"); } this.setMyBatis3JavaMapperType(sb.toString()); sb.setLength(0); sb.append(this.calculateJavaClientInterfacePackage()); sb.append('.'); if (StringUtility.stringHasValue(this.tableConfiguration.getSqlProviderName())) { //支持mapperName = "{0}SqlProvider" 等用法 sb.append(MessageFormat.format(tableConfiguration.getSqlProviderName(), fullyQualifiedTable.getDomainObjectName())); } else { if (StringUtility.stringHasValue(this.fullyQualifiedTable.getDomainObjectSubPackage())) { sb.append(this.fullyQualifiedTable.getDomainObjectSubPackage()); sb.append('.'); } sb.append(this.fullyQualifiedTable.getDomainObjectName()); sb.append("SqlProvider"); } this.setMyBatis3SqlProviderType(sb.toString()); sb.setLength(0); sb.append(this.calculateDynamicSqlSupportPackage()); sb.append('.'); if (StringUtility.stringHasValue(this.tableConfiguration.getDynamicSqlSupportClassName())) { sb.append(this.tableConfiguration.getDynamicSqlSupportClassName()); } else { if (StringUtility.stringHasValue(this.fullyQualifiedTable.getDomainObjectSubPackage())) { sb.append(this.fullyQualifiedTable.getDomainObjectSubPackage()); sb.append('.'); } sb.append(this.fullyQualifiedTable.getDomainObjectName()); sb.append("DynamicSqlSupport"); } this.setMyBatisDynamicSqlSupportType(sb.toString()); if (StringUtility.stringHasValue(this.tableConfiguration.getDynamicSqlTableObjectName())) { this.setMyBatisDynamicSQLTableObjectName(this.tableConfiguration.getDynamicSqlTableObjectName()); } else { this.setMyBatisDynamicSQLTableObjectName(this.fullyQualifiedTable.getDomainObjectName()); } } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/TkMyBatis3SimpleImpl.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3SimpleImpl; import org.mybatis.generator.internal.util.StringUtility; import java.text.MessageFormat; import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; /** * 可以通过MBG1.3.4+版本提供的table元素的mapperName属性设置统一的名称,使用{0}作为实体类名的占位符。 *

* 用法: *

 * <context id="Mysql" targetRuntime="tk.mybatis.mapper.generator.TkMyBatis3SimpleImpl" defaultModelType="flat">
 * </context>
 * 
*

* * @author liuzh * @since 2016-09-04 09:57 */ public class TkMyBatis3SimpleImpl extends IntrospectedTableMyBatis3SimpleImpl { @Override protected String calculateMyBatis3XmlMapperFileName() { StringBuilder sb = new StringBuilder(); if (stringHasValue(tableConfiguration.getMapperName())) { String mapperName = tableConfiguration.getMapperName(); int ind = mapperName.lastIndexOf('.'); if (ind != -1) { mapperName = mapperName.substring(ind + 1); } //支持mapperName = "{0}Dao" 等用法 sb.append(MessageFormat.format(mapperName, fullyQualifiedTable.getDomainObjectName())); sb.append(".xml"); //$NON-NLS-1$ } else { sb.append(fullyQualifiedTable.getDomainObjectName()); sb.append("Mapper.xml"); //$NON-NLS-1$ } return sb.toString(); } @Override protected void calculateJavaClientAttributes() { if (context.getJavaClientGeneratorConfiguration() == null) { return; } StringBuilder sb = new StringBuilder(); sb.append(this.calculateJavaClientInterfacePackage()); sb.append('.'); if (StringUtility.stringHasValue(this.tableConfiguration.getMapperName())) { //支持mapperName = "{0}Dao" 等用法 sb.append(MessageFormat.format(tableConfiguration.getMapperName(), fullyQualifiedTable.getDomainObjectName())); } else { if (StringUtility.stringHasValue(this.fullyQualifiedTable.getDomainObjectSubPackage())) { sb.append(this.fullyQualifiedTable.getDomainObjectSubPackage()); sb.append('.'); } sb.append(this.fullyQualifiedTable.getDomainObjectName()); sb.append("Mapper"); } this.setMyBatis3JavaMapperType(sb.toString()); sb.setLength(0); sb.append(this.calculateJavaClientInterfacePackage()); sb.append('.'); if (StringUtility.stringHasValue(this.tableConfiguration.getSqlProviderName())) { //支持mapperName = "{0}SqlProvider" 等用法 sb.append(MessageFormat.format(tableConfiguration.getSqlProviderName(), fullyQualifiedTable.getDomainObjectName())); } else { if (StringUtility.stringHasValue(this.fullyQualifiedTable.getDomainObjectSubPackage())) { sb.append(this.fullyQualifiedTable.getDomainObjectSubPackage()); sb.append('.'); } sb.append(this.fullyQualifiedTable.getDomainObjectName()); sb.append("SqlProvider"); } this.setMyBatis3SqlProviderType(sb.toString()); sb.setLength(0); sb.append(this.calculateDynamicSqlSupportPackage()); sb.append('.'); if (StringUtility.stringHasValue(this.tableConfiguration.getDynamicSqlSupportClassName())) { sb.append(this.tableConfiguration.getDynamicSqlSupportClassName()); } else { if (StringUtility.stringHasValue(this.fullyQualifiedTable.getDomainObjectSubPackage())) { sb.append(this.fullyQualifiedTable.getDomainObjectSubPackage()); sb.append('.'); } sb.append(this.fullyQualifiedTable.getDomainObjectName()); sb.append("DynamicSqlSupport"); } this.setMyBatisDynamicSqlSupportType(sb.toString()); if (StringUtility.stringHasValue(this.tableConfiguration.getDynamicSqlTableObjectName())) { this.setMyBatisDynamicSQLTableObjectName(this.tableConfiguration.getDynamicSqlTableObjectName()); } else { this.setMyBatisDynamicSQLTableObjectName(this.fullyQualifiedTable.getDomainObjectName()); } } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/file/GenerateByListTemplateFile.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.file; import org.mybatis.generator.api.GeneratedJavaFile; import org.mybatis.generator.api.dom.java.CompilationUnit; import tk.mybatis.mapper.generator.formatter.ListTemplateFormatter; import tk.mybatis.mapper.generator.model.TableClass; import java.util.Properties; import java.util.Set; /** * @author liuzh * @since 3.4.5 */ public class GenerateByListTemplateFile extends GeneratedJavaFile { public static final String ENCODING = "UTF-8"; private String targetPackage; private String fileNameTemplate; private String templateContent; private Properties properties; private Set tableClassSet; private ListTemplateFormatter templateFormatter; public GenerateByListTemplateFile(Set tableClassSet, ListTemplateFormatter templateFormatter, Properties properties, String targetProject, String targetPackage, String fileNameTemplate, String templateContent) { super(null, targetProject, ENCODING, null); this.targetPackage = targetPackage; this.fileNameTemplate = fileNameTemplate; this.templateContent = templateContent; this.properties = properties; this.tableClassSet = tableClassSet; this.templateFormatter = templateFormatter; } @Override public CompilationUnit getCompilationUnit() { return null; } @Override public String getFileName() { return templateFormatter.getFormattedContent(tableClassSet, properties, targetPackage, fileNameTemplate); } @Override public String getFormattedContent() { return templateFormatter.getFormattedContent(tableClassSet, properties, targetPackage, templateContent); } @Override public String getTargetPackage() { return targetPackage; } @Override public boolean isMergeable() { return false; } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/file/GenerateByTemplateFile.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.file; import org.mybatis.generator.api.GeneratedJavaFile; import org.mybatis.generator.api.dom.java.CompilationUnit; import tk.mybatis.mapper.generator.formatter.TemplateFormatter; import tk.mybatis.mapper.generator.model.TableClass; import java.util.Properties; /** * @author liuzh * @since 3.4.5 */ public class GenerateByTemplateFile extends GeneratedJavaFile { public static final String ENCODING = "UTF-8"; private String targetPackage; private String fileName; private String templateContent; private Properties properties; private TableClass tableClass; private TemplateFormatter templateFormatter; public GenerateByTemplateFile(TableClass tableClass, TemplateFormatter templateFormatter, Properties properties, String targetProject, String targetPackage, String fileName, String templateContent) { super(null, targetProject, ENCODING, null); this.targetPackage = targetPackage; this.fileName = fileName; this.templateContent = templateContent; this.properties = properties; this.tableClass = tableClass; this.templateFormatter = templateFormatter; } @Override public CompilationUnit getCompilationUnit() { return null; } @Override public String getFileName() { return templateFormatter.getFormattedContent(tableClass, properties, targetPackage, fileName); } @Override public String getFormattedContent() { return templateFormatter.getFormattedContent(tableClass, properties, targetPackage, templateContent); } @Override public String getTargetPackage() { return templateFormatter.getFormattedContent(tableClass, properties, targetPackage, targetPackage); } @Override public boolean isMergeable() { return false; } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/formatter/FreemarkerTemplateFormatter.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.formatter; import freemarker.cache.StringTemplateLoader; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import tk.mybatis.mapper.generator.model.TableClass; import java.io.StringWriter; import java.io.Writer; import java.util.*; /** * 基于 freemarker 的实现 * * @author liuzh * @since 3.4.5 */ public class FreemarkerTemplateFormatter implements TemplateFormatter, ListTemplateFormatter { private final Configuration configuration = new Configuration(Configuration.VERSION_2_3_23); private final StringTemplateLoader templateLoader = new StringTemplateLoader(); public FreemarkerTemplateFormatter() { configuration.setLocale(Locale.CHINA); configuration.setDefaultEncoding("UTF-8"); configuration.setTemplateLoader(templateLoader); configuration.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_23)); } /** * 根据模板处理 * * @param templateName * @param templateSource * @param params * @return */ public String process(String templateName, String templateSource, Map params) { try { Template template = new Template(templateName, templateSource, configuration); Writer writer = new StringWriter(); template.process(params, writer); return writer.toString(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public String getFormattedContent(TableClass tableClass, Properties properties, String targetPackage, String templateContent) { Map params = new HashMap(); for (Object o : properties.keySet()) { params.put(String.valueOf(o), properties.get(o)); } params.put("props", properties); params.put("package", targetPackage); params.put("tableClass", tableClass); return process(properties.getProperty("templatePath"), templateContent, params); } @Override public String getFormattedContent(Set tableClassSet, Properties properties, String targetPackage, String templateContent) { Map params = new HashMap(); for (Object o : properties.keySet()) { params.put(String.valueOf(o), properties.get(o)); } params.put("props", properties); params.put("package", targetPackage); params.put("tableClassSet", tableClassSet); return process(properties.getProperty("templatePath"), templateContent, params); } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/formatter/ListTemplateFormatter.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.formatter; import tk.mybatis.mapper.generator.model.TableClass; import java.util.Properties; import java.util.Set; /** * @author liuzh * @since 3.4.5 */ public interface ListTemplateFormatter { /** * 获取根据模板生成的数据 * * @param tableClassSet * @param properties * @param targetPackage * @param templateContent * @return */ String getFormattedContent(Set tableClassSet, Properties properties, String targetPackage, String templateContent); } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/formatter/TemplateFormatter.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.formatter; import tk.mybatis.mapper.generator.model.TableClass; import java.util.Properties; /** * @author liuzh * @since 3.4.5 */ public interface TemplateFormatter { /** * 获取根据模板生成的数据 * * @param tableClass * @param properties * @param targetPackage * @param templateContent * @return */ String getFormattedContent(TableClass tableClass, Properties properties, String targetPackage, String templateContent); } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/model/ColumnField.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.model; import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; import java.io.Serializable; /** * @author liuzh * @since 3.4.5 */ public class ColumnField implements Serializable { private static final long serialVersionUID = -435113788623615260L; private TableClass tableClass; private String columnName; private String jdbcType; private String fieldName; private String remarks; private FullyQualifiedJavaType type; private String typePackage; private String shortTypeName; private String fullTypeName; private boolean identity; private boolean nullable; private boolean blobColumn; private boolean stringColumn; private boolean jdbcCharacterColumn; private boolean jdbcDateColumn; private boolean jdbcTimeColumn; private boolean sequenceColumn; private int length; private int scale; public String getColumnName() { return columnName; } public void setColumnName(String columnName) { this.columnName = columnName; } public String getFieldName() { return fieldName; } public void setFieldName(String fieldName) { this.fieldName = fieldName; } public String getFullTypeName() { return fullTypeName; } public void setFullTypeName(String fullTypeName) { this.fullTypeName = fullTypeName; } public String getJdbcType() { return jdbcType; } public void setJdbcType(String jdbcType) { this.jdbcType = jdbcType; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public String getRemarks() { return remarks; } public void setRemarks(String remarks) { this.remarks = remarks; } public int getScale() { return scale; } public void setScale(int scale) { this.scale = scale; } public String getShortTypeName() { return shortTypeName; } public void setShortTypeName(String shortTypeName) { this.shortTypeName = shortTypeName; } public TableClass getTableClass() { return tableClass; } public void setTableClass(TableClass tableClass) { this.tableClass = tableClass; } public FullyQualifiedJavaType getType() { return type; } public void setType(FullyQualifiedJavaType type) { this.type = type; } public String getTypePackage() { return typePackage; } public void setTypePackage(String typePackage) { this.typePackage = typePackage; } public boolean isBlobColumn() { return blobColumn; } public void setBlobColumn(boolean blobColumn) { this.blobColumn = blobColumn; } public boolean isIdentity() { return identity; } public void setIdentity(boolean identity) { this.identity = identity; } public boolean isJdbcCharacterColumn() { return jdbcCharacterColumn; } public void setJdbcCharacterColumn(boolean jdbcCharacterColumn) { this.jdbcCharacterColumn = jdbcCharacterColumn; } public boolean isJdbcDateColumn() { return jdbcDateColumn; } public void setJdbcDateColumn(boolean jdbcDateColumn) { this.jdbcDateColumn = jdbcDateColumn; } public boolean isJdbcTimeColumn() { return jdbcTimeColumn; } public void setJdbcTimeColumn(boolean jdbcTimeColumn) { this.jdbcTimeColumn = jdbcTimeColumn; } public boolean isNullable() { return nullable; } public void setNullable(boolean nullable) { this.nullable = nullable; } public boolean isSequenceColumn() { return sequenceColumn; } public void setSequenceColumn(boolean sequenceColumn) { this.sequenceColumn = sequenceColumn; } public boolean isStringColumn() { return stringColumn; } public void setStringColumn(boolean stringColumn) { this.stringColumn = stringColumn; } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/model/TableClass.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.model; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; import java.io.Serializable; import java.util.List; /** * @author liuzh * @since 3.4.5 */ public class TableClass implements Serializable { private static final long serialVersionUID = -746251813735169289L; private IntrospectedTable introspectedTable; private String tableName; private String variableName; private String lowerCaseName; private String shortClassName; private String fullClassName; private String packageName; private FullyQualifiedJavaType type; private String remarks; private List pkFields; private List baseFields; private List blobFields; private List allFields; public List getAllFields() { return allFields; } public void setAllFields(List allFields) { this.allFields = allFields; } public List getBaseFields() { return baseFields; } public void setBaseFields(List baseFields) { this.baseFields = baseFields; } public List getBlobFields() { return blobFields; } public void setBlobFields(List blobFields) { this.blobFields = blobFields; } public String getFullClassName() { return fullClassName; } public void setFullClassName(String fullClassName) { this.fullClassName = fullClassName; } public IntrospectedTable getIntrospectedTable() { return introspectedTable; } public void setIntrospectedTable(IntrospectedTable introspectedTable) { this.introspectedTable = introspectedTable; } public String getLowerCaseName() { return lowerCaseName; } public void setLowerCaseName(String lowerCaseName) { this.lowerCaseName = lowerCaseName; } public String getPackageName() { return packageName; } public void setPackageName(String packageName) { this.packageName = packageName; } public List getPkFields() { return pkFields; } public void setPkFields(List pkFields) { this.pkFields = pkFields; } public String getShortClassName() { return shortClassName; } public void setShortClassName(String shortClassName) { this.shortClassName = shortClassName; } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public FullyQualifiedJavaType getType() { return type; } public void setType(FullyQualifiedJavaType type) { this.type = type; } public String getVariableName() { return variableName; } public void setVariableName(String variableName) { this.variableName = variableName; } public String getRemarks() { return remarks; } public void setRemarks(String remarks) { this.remarks = remarks; } } ================================================ FILE: generator/src/main/java/tk/mybatis/mapper/generator/model/TableColumnBuilder.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator.model; import org.mybatis.generator.api.FullyQualifiedTable; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; import java.beans.Introspector; import java.util.ArrayList; import java.util.List; /** * @author liuzh * @since 3.4.5 */ public class TableColumnBuilder { /** * 创建 TableClass * * @param introspectedTable * @return */ public static TableClass build(IntrospectedTable introspectedTable) { TableClass tableClass = new TableClass(); tableClass.setIntrospectedTable(introspectedTable); tableClass.setRemarks(introspectedTable.getRemarks()); FullyQualifiedTable fullyQualifiedTable = introspectedTable.getFullyQualifiedTable(); tableClass.setTableName(fullyQualifiedTable.getIntrospectedTableName()); FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()); tableClass.setType(type); tableClass.setVariableName(Introspector.decapitalize(type.getShortName())); tableClass.setLowerCaseName(type.getShortName().toLowerCase()); tableClass.setShortClassName(type.getShortName()); tableClass.setFullClassName(type.getFullyQualifiedName()); tableClass.setPackageName(type.getPackageName()); List pkFields = new ArrayList(); List baseFields = new ArrayList(); List blobFields = new ArrayList(); List allFields = new ArrayList(); for (IntrospectedColumn column : introspectedTable.getPrimaryKeyColumns()) { ColumnField field = build(column); field.setTableClass(tableClass); pkFields.add(field); allFields.add(field); } for (IntrospectedColumn column : introspectedTable.getBaseColumns()) { ColumnField field = build(column); field.setTableClass(tableClass); baseFields.add(field); allFields.add(field); } for (IntrospectedColumn column : introspectedTable.getBLOBColumns()) { ColumnField field = build(column); field.setTableClass(tableClass); blobFields.add(field); allFields.add(field); } tableClass.setPkFields(pkFields); tableClass.setBaseFields(baseFields); tableClass.setBlobFields(blobFields); tableClass.setAllFields(allFields); return tableClass; } /** * 创建 ColumnField * * @param column * @return */ public static ColumnField build(IntrospectedColumn column) { ColumnField field = new ColumnField(); field.setColumnName(column.getActualColumnName()); field.setJdbcType(column.getJdbcTypeName()); field.setFieldName(column.getJavaProperty()); field.setRemarks(column.getRemarks()); FullyQualifiedJavaType type = column.getFullyQualifiedJavaType(); field.setType(type); field.setTypePackage(type.getPackageName()); field.setShortTypeName(type.getShortName()); field.setFullTypeName(type.getFullyQualifiedName()); field.setIdentity(column.isIdentity()); field.setNullable(column.isNullable()); field.setSequenceColumn(column.isSequenceColumn()); field.setBlobColumn(column.isBLOBColumn()); field.setStringColumn(column.isStringColumn()); field.setJdbcCharacterColumn(column.isJdbcCharacterColumn()); field.setJdbcDateColumn(column.isJDBCDateColumn()); field.setJdbcTimeColumn(column.isJDBCTimeColumn()); field.setLength(column.getLength()); field.setScale(column.getScale()); return field; } } ================================================ FILE: generator/src/main/resources/generator/mapper.ftl ================================================ package ${package}; import ${tableClass.fullClassName}; /** * 通用 Mapper 代码生成器 * * @author mapper-generator */ public interface ${tableClass.shortClassName}${mapperSuffix} extends ${baseMapper!"tk.mybatis.mapper.common.Mapper"}<${tableClass.shortClassName}> { } ================================================ FILE: generator/src/main/resources/generator/mapperXml.ftl ================================================ ================================================ FILE: generator/src/main/resources/generator/test-all.ftl ================================================ 目标package: ${package} 当前时间: <#assign dateTime = .now> ${dateTime?date} ${dateTime?time} ${dateTime?string["yyyy-MM-dd HH:mm:ss"]} 所有配置的属性信息: <#list props?keys as key> ${key} - ${props[key]} <#list tableClassSet as tableClass> **************************************************************************************** 实体和表的信息: 表名:${tableClass.tableName} 表注释:${tableClass.remarks!""} 变量名:${tableClass.variableName} 小写名:${tableClass.lowerCaseName} 类名:${tableClass.shortClassName} 全名:${tableClass.fullClassName} 包名:${tableClass.packageName} 列的信息: ===================================== <#if tableClass.pkFields??> 主键: <#list tableClass.pkFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} <#if field.remarks??> 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} <#if tableClass.baseFields??> 基础列: <#list tableClass.baseFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} <#if field.remarks??> 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} <#if tableClass.blobFields??> Blob列: <#list tableClass.blobFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} <#if field.remarks??> 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} ===================================== 全部列: <#if tableClass.allFields??> 列名 - 字段名 <#list tableClass.allFields as field> ${field.columnName} - ${field.fieldName} ================================================ FILE: generator/src/main/resources/generator/test-one.ftl ================================================ 目标package: ${package} 当前时间: <#assign dateTime = .now> ${dateTime?date} ${dateTime?time} ${dateTime?string["yyyy-MM-dd HH:mm:ss"]} 所有配置的属性信息: <#list props?keys as key> ${key} - ${props[key]} 实体和表的信息: 表名:${tableClass.tableName} 表注释:${tableClass.remarks!""} 变量名:${tableClass.variableName} 小写名:${tableClass.lowerCaseName} 类名:${tableClass.shortClassName} 全名:${tableClass.fullClassName} 包名:${tableClass.packageName} 列的信息: ===================================== <#if tableClass.pkFields??> 主键: <#list tableClass.pkFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} <#if field.remarks??> 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} <#if tableClass.baseFields??> 基础列: <#list tableClass.baseFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} <#if field.remarks??> 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} <#if tableClass.blobFields??> Blob列: <#list tableClass.blobFields as field> ------------------------------------- 列名:${field.columnName} 列类型:${field.jdbcType} 字段名:${field.fieldName} <#if field.remarks??> 注释:${field.remarks} 类型包名:${field.typePackage} 类型短名:${field.shortTypeName} 类型全名:${field.fullTypeName} 是否主键:${field.identity?c} 是否可空:${field.nullable?c} 是否为BLOB列:${field.blobColumn?c} 是否为String列:${field.stringColumn?c} 是否为字符串列:${field.jdbcCharacterColumn?c} 是否为日期列:${field.jdbcDateColumn?c} 是否为时间列:${field.jdbcTimeColumn?c} 是否为序列列:${field.sequenceColumn?c} 列长度:${field.length?c} 列精度:${field.scale} ===================================== 全部列: <#if tableClass.allFields??> 列名 - 字段名 <#list tableClass.allFields as field> ${field.columnName} - ${field.fieldName} ================================================ FILE: generator/src/test/java/tk/mybatis/mapper/generator/Generator.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.generator; import org.hsqldb.cmdline.SqlFile; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DriverManager; import java.util.ArrayList; import java.util.List; /** * @author liuzh */ public class Generator { public static void startDB() { try { Class.forName("org.hsqldb.jdbcDriver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } String url = "jdbc:hsqldb:mem:generator"; String user = "sa"; String password = ""; try { Connection connection = DriverManager.getConnection(url, user, password); InputStream inputStream = getResourceAsStream("CreateDB.sql"); SqlFile sqlFile = new SqlFile(new InputStreamReader(inputStream), "init", System.out, "UTF-8", false, new File(".")); sqlFile.setConnection(connection); sqlFile.execute(); connection.close(); } catch (Exception e) { e.printStackTrace(); } } public static InputStream getResourceAsStream(String path) { return Thread.currentThread().getContextClassLoader().getResourceAsStream(path); } public static void main(String[] args) throws Exception { startDB(); List warnings = new ArrayList(); boolean overwrite = true; ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(getResourceAsStream("generatorConfig.xml")); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); for (String warning : warnings) { System.out.println(warning); } } } ================================================ FILE: generator/src/test/resources/CreateDB.sql ================================================ drop table country if exists; create table country ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) DEFAULT 'HH', decimal_num decimal(10, 5) DEFAULT 0.1, version INTEGER DEFAULT 1 NOT NULL ); drop table user_info if exists; --用户信息表 create table user_info ( id integer GENERATED BY DEFAULT AS IDENTITY(START WITH 6) NOT NULL PRIMARY KEY, username varchar(32) NOT NULL, password varchar(32) DEFAULT '12345678', usertype varchar(2), enabled integer, realname varchar(50), qq varchar(12), email varchar(100), address varchar(200), tel varchar(30) ); insert into user_info (id, username, password, usertype) values (1, 'test1', '12345678', '1'); insert into user_info (id, username, password, usertype) values (2, 'test2', 'aaaa', '2'); insert into user_info (id, username, password, usertype) values (3, 'test3', 'bbbb', '1'); insert into user_info (id, username, password, usertype) values (4, 'test4', 'cccc', '2'); insert into user_info (id, username, password, usertype) values (5, 'test5', 'dddd', '1'); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); ================================================ FILE: generator/src/test/resources/generatorConfig.xml ================================================
================================================ FILE: pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} pom mapper-modules Mybatis 通用 Mapper 聚合模块 https://mybatis.io 6.0.0 17 17 UTF-8 UTF-8 3.2.0 2.0.17 3.5.19 1.2.4 2.1.2 1.0.4 4.13.2 2.7.3 1.5.25 The MIT License (MIT) https://github.com/abel533/mapper/blob/master/LICENSE abel533 abel533@gmail.com jakarta.persistence jakarta.persistence-api ${jpa.version} org.mybatis mybatis ${mybatis.version} org.mybatis.scripting mybatis-freemarker ${mybatis-freemarker.version} true org.mybatis.scripting mybatis-velocity ${mybatis-velocity.version} true org.mybatis.scripting mybatis-thymeleaf ${mybatis-thymeleaf.version} true org.slf4j slf4j-api ${slf4j.version} true ch.qos.logback logback-classic ${logback.version} true junit junit ${junit.version} test org.hsqldb hsqldb ${hsqldb.version} test org.slf4j slf4j-api junit junit ch.qos.logback logback-classic org.hsqldb hsqldb scm:git@github.com:abel533/mapper.git scm:git@github.com:abel533/mapper.git git@github.com:abel533/mapper.git all base core extra spring weekend generator spring-boot-starter solon-plugin src/test/resources src/test/java org.apache.maven.plugins maven-compiler-plugin 3.13.0 -parameters org.codehaus.mojo flatten-maven-plugin 1.6.0 true resolveCiFriendliesOnly flatten process-resources flatten flatten.clean clean clean release org.apache.maven.plugins maven-source-plugin 3.3.1 package jar-no-fork org.apache.maven.plugins maven-javadoc-plugin 3.8.0 -Xdoclint:none package jar org.apache.maven.plugins maven-gpg-plugin 3.2.5 sign-artifacts verify sign --pinentry-mode loopback org.sonatype.central central-publishing-maven-plugin 0.4.0 true central true true central https://central.sonatype.com/api/v1/publisher/upload central https://central.sonatype.com/api/v1/publisher/upload ================================================ FILE: solon-plugin/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-solon-plugin jar mapper-solon-plugin Solon Support for Mapper https://github.com/abel533/solon-plugin/ 2.7.3 org.noear mybatis-solon-plugin ${solon.version} tk.mybatis mapper-core ${project.version} tk.mybatis mapper-base ${project.version} org.noear solon-test-junit4 ${solon.version} test com.h2database h2 1.4.200 test com.zaxxer HikariCP 5.1.0 test ================================================ FILE: solon-plugin/src/main/java/tk/mybatis/solon/TkMapperAdapterFactory.java ================================================ package tk.mybatis.solon; import org.apache.ibatis.solon.MybatisAdapter; import org.apache.ibatis.solon.MybatisAdapterFactory; import org.noear.solon.core.BeanWrap; import org.noear.solon.core.Props; /** * @title: tkMybatis Adapter Factory * @author: trifolium.wang * @date: 2024/4/1 * @since 2.7.3 */ public class TkMapperAdapterFactory implements MybatisAdapterFactory { @Override public MybatisAdapter create(BeanWrap dsWrap) { return new TkMapperMybatisAdapter(dsWrap); } @Override public MybatisAdapter create(BeanWrap dsWrap, Props dsProps) { return new TkMapperMybatisAdapter(dsWrap, dsProps); } } ================================================ FILE: solon-plugin/src/main/java/tk/mybatis/solon/TkMapperMybatisAdapter.java ================================================ package tk.mybatis.solon; import org.apache.ibatis.mapping.Environment; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.solon.integration.MybatisAdapterDefault; import org.noear.solon.core.BeanWrap; import org.noear.solon.core.Props; import org.noear.solon.core.PropsConverter; import org.noear.solon.core.VarHolder; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; /** * @title: TkMybatis Adapter * @author: trifolium.wang * @date: 2024/4/1 * @since 2.7.3 */ public class TkMapperMybatisAdapter extends MybatisAdapterDefault { protected Config tkConfig; protected MapperHelper mapperHelper; protected TkMapperMybatisAdapter(BeanWrap dsWrap) { super(dsWrap); dsWrap.context().getBeanAsync(Config.class, bean -> { tkConfig = bean; }); dsWrap.context().getBeanAsync(MapperHelper.class, bean -> { mapperHelper = bean; }); } protected TkMapperMybatisAdapter(BeanWrap dsWrap, Props dsProps) { super(dsWrap, dsProps); dsWrap.context().getBeanAsync(Config.class, bean -> { tkConfig = bean; }); dsWrap.context().getBeanAsync(MapperHelper.class, bean -> { mapperHelper = bean; }); } @Override protected void initConfiguration(Environment environment) { config = new tk.mybatis.mapper.session.Configuration(); config.setEnvironment(environment); Props mybatisProps = dsProps.getProp("configuration"); if (!mybatisProps.isEmpty()) { PropsConverter.global().convert(mybatisProps, config, Configuration.class, null); } } @Override public SqlSessionFactory getFactory() { if (factory == null) { builderMapperHelper(); factory = factoryBuilder.build(config); } return factory; } @Override public void injectTo(VarHolder varH) { super.injectTo(varH); //@Db("db1") Config tkConfig; if (Config.class.isAssignableFrom(varH.getType())) { varH.setValue(this.tkConfig); } //@Db("db1") tk.mybatis.mapper.session.Configuration configuration; if (tk.mybatis.mapper.session.Configuration.class.isAssignableFrom(varH.getType())) { varH.setValue(getConfiguration()); } //@Db("db1") MapperHelper mapperHelper; if (MapperHelper.class.isAssignableFrom(varH.getType())) { varH.setValue(this.mapperHelper); } } /** * 通过使用 tk.mybatis.mapper.session.Configuration * 替换 MyBatis 中的 org.apache.ibatis.session.Configuration. * 重写原 Configuration 中的 addMappedStatement实现 */ private void builderMapperHelper() { Props cfgProps = dsProps.getProp("tk.mapper"); if (tkConfig == null) { tkConfig = new Config(); } if (!cfgProps.isEmpty()) { PropsConverter.global().convert(cfgProps, tkConfig, Config.class, null); } if (mapperHelper == null) { mapperHelper = new MapperHelper(); } mapperHelper.setConfig(tkConfig); ((tk.mybatis.mapper.session.Configuration) config).setMapperHelper(mapperHelper); } } ================================================ FILE: solon-plugin/src/main/java/tk/mybatis/solon/XPluginImpl.java ================================================ package tk.mybatis.solon; import org.apache.ibatis.solon.integration.MybatisAdapterManager; import org.noear.solon.core.AppContext; import org.noear.solon.core.Plugin; /** * @title: TkMybatis的Solon插件 * @author: trifolium.wang * @date: 2024/4/1 * @since 2.7.3 */ public class XPluginImpl implements Plugin { @Override public void start(AppContext context) throws Throwable { MybatisAdapterManager.setAdapterFactory(new TkMapperAdapterFactory()); } } ================================================ FILE: solon-plugin/src/main/resources/META-INF/solon/mybatis-tkmapper-solon-plugin.properties ================================================ solon.plugin=tk.mybatis.solon.XPluginImpl solon.plugin.priority=3 ================================================ FILE: solon-plugin/src/test/java/tk/mybatis/solon/test/TkMapperTest.java ================================================ package tk.mybatis.solon.test; import org.noear.solon.Solon; /** * @title: TkMapperTest * @author: trifolium.wang * @date: 2024/4/2 */ public class TkMapperTest { public static void main(String[] args) { Solon.start(TkMapperTest.class, args); } } ================================================ FILE: solon-plugin/src/test/java/tk/mybatis/solon/test/conf/TestConfig.java ================================================ package tk.mybatis.solon.test.conf; import com.zaxxer.hikari.HikariDataSource; import org.noear.solon.annotation.Bean; import org.noear.solon.annotation.Configuration; import org.noear.solon.annotation.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.sql.DataSource; import java.sql.Connection; import java.sql.Statement; /** * @title: TestConfig * @author: trifolium.wang * @date: 2024/4/2 */ @Configuration public class TestConfig { Logger log = LoggerFactory.getLogger(TestConfig.class); @Bean(name = "db1", typed = true) public DataSource db1(@Inject("${test.db1}") HikariDataSource ds) { try { Connection conn = ds.getConnection(); Statement statement = conn.createStatement(); statement.execute("CREATE TABLE user (" + " `id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY," + " `name` varchar(255) DEFAULT NULL," + " `age` int DEFAULT NULL," + " `create_time` datetime DEFAULT NULL," + " `is_del` tinyint(1) DEFAULT NULL" + ")"); statement.execute("INSERT INTO `user` (`id`, `name`, `age`, `create_time`, `is_del`) VALUES (1, '张三', 11, '2024-04-02 13:38:56', 0);\n" + "INSERT INTO `user` (`id`, `name`, `age`, `create_time`, `is_del`) VALUES (2, '李四', 3, '2024-04-02 13:39:08', 0);\n" + "INSERT INTO `user` (`id`, `name`, `age`, `create_time`, `is_del`) VALUES (3, '张麻子', 43, '2024-04-02 13:39:20', 0);"); statement.close(); conn.close(); } catch (Exception e) { log.error(e.getMessage(), e); throw new RuntimeException("Datasource initialization Failure!"); } return ds; } } ================================================ FILE: solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java ================================================ package tk.mybatis.solon.test.entity; import org.noear.snack.core.utils.DateUtil; import tk.mybatis.mapper.annotation.LogicDelete; import jakarta.persistence.Column; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.util.Date; @Table(name = "`user`") public class User { @Id @Column(name = "id") @GeneratedValue(generator = "JDBC") private Long id; @Column(name = "`name`") private String name; @Column(name = "age") private Integer age; @Column(name = "create_time") private Date createTime; @LogicDelete @Column(name = "is_del") private Boolean isDel; /** * @return id */ public Long getId() { return id; } /** * @param id */ public void setId(Long id) { this.id = id; } /** * @return name */ public String getName() { return name; } /** * @param name */ public void setName(String name) { this.name = name; } /** * @return age */ public Integer getAge() { return age; } /** * @param age */ public void setAge(Integer age) { this.age = age; } /** * @return create_time */ public Date getCreateTime() { return createTime; } /** * @param createTime */ public void setCreateTime(Date createTime) { this.createTime = createTime; } /** * @return is_del */ public Boolean getIsDel() { return isDel; } /** * @param isDel */ public void setIsDel(Boolean isDel) { this.isDel = isDel; } @Override public String toString() { return String.format("id:%d, name:%s, age:%d, createTime:%s", id, name, age, createTime != null ? DateUtil.format(createTime, DateUtil.FORMAT_19_b) : null); } } ================================================ FILE: solon-plugin/src/test/java/tk/mybatis/solon/test/mapper/UserMapper.java ================================================ package tk.mybatis.solon.test.mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.solon.test.entity.User; import java.util.List; public interface UserMapper extends Mapper { @ResultMap("tk.mybatis.solon.test.mapper.UserMapper.BaseResultMap") @Select("SELECT * FROM user WHERE is_del = 0 AND age > #{age}") List findByGTAge(@Param("age") Integer age); List findByName(@Param("name") String name); } ================================================ FILE: solon-plugin/src/test/java/tk/mybatis/solon/test/service/TkMapperServiceTest.java ================================================ package tk.mybatis.solon.test.service; import org.apache.ibatis.solon.annotation.Db; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.noear.solon.test.SolonJUnit4ClassRunner; import org.noear.solon.test.SolonTest; import org.noear.solon.test.annotation.Rollback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tk.mybatis.mapper.entity.Example; import tk.mybatis.solon.test.TkMapperTest; import tk.mybatis.solon.test.entity.User; import tk.mybatis.solon.test.mapper.UserMapper; import java.util.List; /** * @title: TkMapperServiceTest * @author: trifolium.wang * @date: 2024/4/2 */ //@Ignore @SolonTest(TkMapperTest.class) @RunWith(SolonJUnit4ClassRunner.class) public class TkMapperServiceTest { Logger log = LoggerFactory.getLogger(TkMapperServiceTest.class); @Db("db1") private UserMapper userMapper; @Test public final void all() { userMapper.selectAll().forEach(u -> log.info(u.toString())); } /** * 根据主键查询 */ @Test public final void byId() { User user = userMapper.selectByPrimaryKey(1); log.info(user == null ? null : user.toString()); } /** * 根据example查询 */ @Test public final void exampleQuery() { Example example = new Example(User.class); example.and().andLike("name", "%张%"); userMapper.selectByExample(example).forEach(u -> log.info(u.toString())); } /** * mybatis 原生查询 */ @Test public final void rawMybatisQuery() { userMapper.findByGTAge(11).forEach(u -> log.info(u.toString())); } /** * mybatis 逻辑删除和添加,并测试事务 */ @Test @Rollback public final void logicDelInsert() { List users = userMapper.findByName("张麻子"); if (!users.isEmpty()) { User user = users.get(0); userMapper.deleteByPrimaryKey(user.getId()); user.setId(null); userMapper.insert(user); } } } ================================================ FILE: solon-plugin/src/test/resources/app.yml ================================================ # 配置数据源 test: db1: jdbcUrl: jdbc:h2:mem:h2DB driverClassName: org.h2.Driver username: root password: root mybatis: db1: typeAliases: - "tk.mybatis.solon.test.entity.*" mappers: - "classpath:mapper/*.xml" # tk mapper的配置 tk: mapper: style: camelhumpandlowercase safe-update: true safe-delete: true ================================================ FILE: solon-plugin/src/test/resources/mapper/UserMapper.xml ================================================ id, `name`, age, create_time, is_del ================================================ FILE: spring/README.md ================================================ # Mybatis 通用 Mapper 和 Spring 集成 [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-spring/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-spring) ## 依赖 项目自身依赖不传递(`provided`),因此需要自己提供其他依赖: > 正常情况下,也是在这些依赖基础上增加的 mapper-spring ```xml tk.mybatis mapper-spring 版本号 ``` 其他依赖 ```xml org.mybatis mybatis 版本号 tk.mybatis mapper 版本号 org.mybatis mybatis-spring 版本号 org.springframework spring-context 版本号 org.springframework spring-tx 版本号 org.springframework spring-jdbc 版本号 ``` ## 配置 本项目主要提供了两种大的配置方式。 - `MapperScannerConfigurer` xml bean 配置 - `@MapperScan` 注解 除此之外,高版本的 MyBatis (3.4.0+) 和 mybatis-spring (1.3.0+) 中还有一种推荐的 `tk.mybatis.mapper.session.Configuration` 配置。 > 通用 Mapper 3.6.0 之后会自动注册带有 `@RegisterMapper` 注解的**基类**接口,不在强制要求配置 mappers 属性,只需要给你的基类加 `@RegisterMapper` 注解即可。 ### 初次使用通用 Mapper 请注意 下面的示例只是演示如何进行配置,具体配置那些参数要自己选择! 所有可配置参数请参考通用 Mapper 文档: > https://github.com/abel533/Mapper/blob/master/wiki/mapper3/2.Integration.md ### 一、`MapperScannerConfigurer` xml bean 配置 ```xml mappers=tk.mybatis.mapper.common.Mapper ``` 注意两点: 1. 这里使用的 `tk.mybatis.spring.mapper.MapperScannerConfigurer`,不是官方的 `org.xxx` 2. 所有对通用 Mapper 的配置,参考上面的 mappers=xxx,一行写一个配置即可 ### 二、`@MapperScan` 注解 纯注解使用的时候,通用 Mapper 的参数不能像原来那样直接配置,为了适应这种方式,提供了三种可用的方式。 下面按照优先级由高到低的顺序来讲注解配置用法。 #### 1. 使用 `mapperHelperRef` 配置 ```java @Configuration @MapperScan(value = "tk.mybatis.mapper.mapper", mapperHelperRef = "mapperHelper") public static class MyBatisConfigRef { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("CreateDB.sql") .build(); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); return sessionFactory.getObject(); } @Bean public MapperHelper mapperHelper() { Config config = new Config(); List mappers = new ArrayList(); mappers.add(Mapper.class); config.setMappers(mappers); MapperHelper mapperHelper = new MapperHelper(); mapperHelper.setConfig(config); return mapperHelper; } } ``` 在这个例子中 `@MapperScan` 唯一特殊的地方在于 `mapperHelperRef` 属性,这个属性用于指定 MapperHelper bean 的 `name`,这里的名字和代码中配置的 `mapperHelper()` 的方法名一致。 > Spring 中默认的 name 就是方法名,还可以通过 `@Bean` 注解指定 `name`。 在这种配置方式中,你可以很方便的控制 `MapperHelper` 中的各项配置。 #### 2. 使用 `properties` 配置 ```java @Configuration @MapperScan(value = "tk.mybatis.mapper.mapper", properties = { "mappers=tk.mybatis.mapper.common.Mapper", "notEmpty=true" } ) public static class MyBatisConfigProperties { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("CreateDB.sql") .build(); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); return sessionFactory.getObject(); } } ``` 如上面代码中所示,这种配置方式和 xml bean 的方式比较接近,就是通过一行一行的 `xx=xxx` 对通用 Mapper 进行配置,配置时参考这里的示例配置即可。 #### 3. Spring Boot 环境中使用 `application.[yml|properties]` 配置文件 在 Spring Boot 中使用 Mapper 时,如果选择使用注解方式(可以不引入 mapper-starter 依赖),就可以选择这第 3 种方式。 > 特别提醒:Spring Boot 中常见的是配置文件方式,使用环境变量或者运行时的参数都可以配置,这些配置都可以对通用 Mapper 生效。 例如在 yml 格式中配置: ```yml mapper: mappers: - tk.mybatis.mapper.common.Mapper - tk.mybatis.mapper.common.Mapper2 not-empty: true ``` 在 propertie 配置中: ```properties mapper.mappers=tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.Mapper2 mapper.not-empty=true ``` > 特别提醒:Spring Boot 中支持 relax 方式的参数配置,但是前面两种方式都不支持,前两种配置参数的时候需要保证大小写一致! ### 三、`tk.mybatis.mapper.session.Configuration` 配置 **使用要求:MyBatis (3.4.0+) 和 mybatis-spring (1.3.0+)** 注意该类的包名,这个类继承了 MyBatis 的 `Configuration` 类,并且重写了 `addMappedStatement` 方法,如下: ```java @Override public void addMappedStatement(MappedStatement ms) { try { super.addMappedStatement(ms); //在这里处理时,更能保证所有的方法都会被正确处理 if (this.mapperHelper != null) { this.mapperHelper.processMappedStatement(ms); } } catch (IllegalArgumentException e) { //这里的异常是导致 Spring 启动死循环的关键位置,为了避免后续会吞异常,这里直接输出 e.printStackTrace(); throw new RuntimeException(e); } } ``` `tk.mybatis.mapper.session.Configuration` 提供了 3 种配置通用 Mapper 的方式,如下所示: ```java /** * 直接注入 mapperHelper * * @param mapperHelper */ public void setMapperHelper(MapperHelper mapperHelper) { this.mapperHelper = mapperHelper; } /** * 使用属性方式配置 * * @param properties */ public void setMapperProperties(Properties properties) { if (this.mapperHelper == null) { this.mapperHelper = new MapperHelper(); } this.mapperHelper.setProperties(properties); } /** * 使用 Config 配置 * * @param config */ public void setConfig(Config config) { if (mapperHelper == null) { mapperHelper = new MapperHelper(); } mapperHelper.setConfig(config); } ``` 使用 `tk.mybatis.mapper.session.Configuration` 有两种和 Spring 集成的配置方法 #### 1. Spring XML 配置 配置如下: ```xml notEmpty=true ``` > 特别注意:这种情况下的 MapperScannerConfigurer 是官方 mybatis-spring 中提供的类,不是 tk 开头的! 参考这里的配置即可,注意和其他方式的区别。 这里直接配置一个 tk 中提供的 `Configuration`,然后注入到 `SqlSessionFactoryBean` 中。 #### 2. 注解方式 ```java @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); //创建 Configuration,设置通用 Mapper 配置 tk.mybatis.mapper.session.Configuration configuration = new tk.mybatis.mapper.session.Configuration(); //有 3 种配置方式 configuration.setMapperHelper(new MapperHelper()); sessionFactory.setConfiguration(configuration); return sessionFactory.getObject(); } ``` 看上述代码以及注释。 ================================================ FILE: spring/license.txt ================================================ Copyright ${license.git.copyrightYears} the original author or authors. 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 http://www.apache.org/licenses/LICENSE-2.0 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. ================================================ FILE: spring/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-spring jar mapper-spring Mybatis 通用 Mapper 和 Spring 集成 7.0.3 4.0.0 org.slf4j slf4j-api org.mybatis mybatis tk.mybatis mapper-core ${project.version} provided tk.mybatis mapper-base ${project.version} provided org.mybatis mybatis-spring ${mybatis-spring.version} provided org.springframework spring-context ${spring.version} provided org.springframework spring-tx ${spring.version} provided org.springframework spring-jdbc ${spring.version} provided ================================================ FILE: spring/src/main/java/tk/mybatis/spring/annotation/BaseProperties.java ================================================ package tk.mybatis.spring.annotation; /** * @author liuzh */ public class BaseProperties { public static final String MYBATIS_PREFIX = "mybatis"; /** * Base packages to scan for MyBatis interfaces. Note that only interfaces * with at least one method will be registered; concrete classes will be * ignored. */ private String[] basePackages; public String[] getBasePackages() { return basePackages; } public void setBasePackages(String[] basePackages) { this.basePackages = basePackages; } } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/annotation/MapperScan.java ================================================ /* * Copyright 2010-2023 the original author or authors. * * 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 * * https://www.apache.org/licenses/LICENSE-2.0 * * 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 tk.mybatis.spring.annotation; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AliasFor; import tk.mybatis.spring.mapper.MapperFactoryBean; import tk.mybatis.spring.mapper.MapperScannerConfigurer; import java.lang.annotation.*; /** * Use this annotation to register MyBatis mapper interfaces when using Java Config. It performs when same work as * {@link MapperScannerConfigurer} via {@link MapperScannerRegistrar}. *

* Either {@link #basePackageClasses} or {@link #basePackages} (or its alias {@link #value}) may be specified to define * specific packages to scan. Since 2.0.4, If specific packages are not defined, scanning will occur from the package of * the class that declares this annotation. *

* Configuration example: *

* *
 * @Configuration
 * @MapperScan("org.mybatis.spring.sample.mapper")
 * public class AppConfig {
 *
 *   @Bean
 *   public DataSource dataSource() {
 *     return new EmbeddedDatabaseBuilder().addScript("schema.sql").build();
 *   }
 *
 *   @Bean
 *   public DataSourceTransactionManager transactionManager() {
 *     return new DataSourceTransactionManager(dataSource());
 *   }
 *
 *   @Bean
 *   public SqlSessionFactory sqlSessionFactory() throws Exception {
 *     SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
 *     sessionFactory.setDataSource(dataSource());
 *     return sessionFactory.getObject();
 *   }
 * }
 * 
* * @author Michael Lanyon * @author Eduardo Macarron * @author Qimiao Chen * @see MapperScannerRegistrar * @see MapperFactoryBean * @since 1.2.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.class) @Repeatable(MapperScans.class) public @interface MapperScan { /** * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.: * {@code @MapperScan("org.my.pkg")} instead of {@code @MapperScan(basePackages = "org.my.pkg"})}. * * @return base package names */ @AliasFor("basePackages") String[] value() default {}; /** * Base packages to scan for MyBatis interfaces. Note that only interfaces with at least one method will be * registered; concrete classes will be ignored. * * @return base package names for scanning mapper interface */ @AliasFor("value") String[] basePackages() default {}; /** * Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The * package of each class specified will be scanned. *

* Consider creating a special no-op marker class or interface in each package that serves no purpose other than being * referenced by this attribute. * * @return classes that indicate base package for scanning mapper interface */ Class[] basePackageClasses() default {}; /** * The {@link BeanNameGenerator} class to be used for naming detected components within the Spring container. * * @return the class of {@link BeanNameGenerator} */ Class nameGenerator() default BeanNameGenerator.class; /** * This property specifies the annotation that the scanner will search for. *

* The scanner will register all interfaces in the base package that also have the specified annotation. *

* Note this can be combined with markerInterface. * * @return the annotation that the scanner will search for */ Class annotationClass() default Annotation.class; /** * This property specifies the parent that the scanner will search for. *

* The scanner will register all interfaces in the base package that also have the specified interface class as a * parent. *

* Note this can be combined with annotationClass. * * @return the parent that the scanner will search for */ Class markerInterface() default Class.class; /** * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. * * @return the bean name of {@code SqlSessionTemplate} */ String sqlSessionTemplateRef() default ""; /** * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. * * @return the bean name of {@code SqlSessionFactory} */ String sqlSessionFactoryRef() default ""; /** * Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean. * * @return the class of {@code MapperFactoryBean} */ Class factoryBean() default MapperFactoryBean.class; /** * Whether enable lazy initialization of mapper bean. *

* Default is {@code false}. *

* * @return set {@code true} to enable lazy initialization * @since 2.0.2 */ String lazyInitialization() default ""; /** * Specifies the default scope of scanned mappers. *

* Default is {@code ""} (equiv to singleton). *

* * @return the default scope */ String defaultScope() default AbstractBeanDefinition.SCOPE_DEFAULT; /** * Specifies a flag that whether execute a property placeholder processing or not. *

* The default is {@literal true}. This means that a property placeholder processing execute. * * @return a flag that whether execute a property placeholder processing or not * @since 3.0.3 */ boolean processPropertyPlaceHolders() default true; /** * Specifies which types are not eligible for mapper scanning. * * @return array of customized mapper excludeFilter * @since 3.0.3 */ ComponentScan.Filter[] excludeFilters() default {}; /** * 通用 Mapper 的配置,一行一个配置 * * @return */ String[] properties() default {}; /** * 还可以直接配置一个 MapperHelper bean * * @return */ String mapperHelperRef() default ""; } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/annotation/MapperScannerRegistrar.java ================================================ /* * Copyright 2010-2024 the original author or authors. * * 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 * * https://www.apache.org/licenses/LICENSE-2.0 * * 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 tk.mybatis.spring.annotation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import tk.mybatis.spring.mapper.ClassPathMapperScanner; import tk.mybatis.spring.mapper.MapperFactoryBean; import tk.mybatis.spring.mapper.MapperScannerConfigurer; import java.lang.annotation.Annotation; import java.util.*; import java.util.stream.Collectors; /** * A {@link ImportBeanDefinitionRegistrar} to allow annotation configuration of MyBatis mapper scanning. Using * an @Enable annotation allows beans to be registered via @Component configuration, whereas implementing * {@code BeanDefinitionRegistryPostProcessor} will work for XML configuration. * * @author Michael Lanyon * @author Eduardo Macarron * @author Putthiphong Boonphong * * @see MapperFactoryBean * @see ClassPathMapperScanner * * @since 1.2.0 */ public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware { public static final Logger LOGGER = LoggerFactory.getLogger(MapperScannerRegistrar.class); // Note: Do not move resourceLoader via cleanup private ResourceLoader resourceLoader; private Environment environment; @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { var mapperScanAttrs = AnnotationAttributes .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); if (mapperScanAttrs != null) { registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0)); } } void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) { var builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); builder.addPropertyValue("processPropertyPlaceHolders", annoAttrs.getBoolean("processPropertyPlaceHolders")); Class annotationClass = annoAttrs.getClass("annotationClass"); if (!Annotation.class.equals(annotationClass)) { builder.addPropertyValue("annotationClass", annotationClass); } Class markerInterface = annoAttrs.getClass("markerInterface"); if (!Class.class.equals(markerInterface)) { builder.addPropertyValue("markerInterface", markerInterface); } Class generatorClass = annoAttrs.getClass("nameGenerator"); if (!BeanNameGenerator.class.equals(generatorClass)) { builder.addPropertyValue("nameGenerator", BeanUtils.instantiateClass(generatorClass)); } Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass); } var sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef"); if (StringUtils.hasText(sqlSessionTemplateRef)) { builder.addPropertyValue("sqlSessionTemplateBeanName", annoAttrs.getString("sqlSessionTemplateRef")); } var sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef"); if (StringUtils.hasText(sqlSessionFactoryRef)) { builder.addPropertyValue("sqlSessionFactoryBeanName", annoAttrs.getString("sqlSessionFactoryRef")); } List basePackages = new ArrayList<>(Arrays.stream(annoAttrs.getStringArray("basePackages")) .filter(StringUtils::hasText).collect(Collectors.toList())); basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName) .collect(Collectors.toList())); if (basePackages.isEmpty()) { basePackages.add(getDefaultBasePackage(annoMeta)); } var excludeFilterArray = annoAttrs.getAnnotationArray("excludeFilters"); if (excludeFilterArray.length > 0) { List typeFilters = new ArrayList<>(); List> rawTypeFilters = new ArrayList<>(); for (AnnotationAttributes excludeFilters : excludeFilterArray) { if (excludeFilters.getStringArray("pattern").length > 0) { // in oder to apply placeholder resolver rawTypeFilters.addAll(parseFiltersHasPatterns(excludeFilters)); } else { typeFilters.addAll(typeFiltersFor(excludeFilters)); } } builder.addPropertyValue("excludeFilters", typeFilters); builder.addPropertyValue("rawExcludeFilters", rawTypeFilters); } //优先级 mapperHelperRef > properties > springboot String mapperHelperRef = annoAttrs.getString("mapperHelperRef"); String[] properties = annoAttrs.getStringArray("properties"); if (StringUtils.hasText(mapperHelperRef)) { builder.addPropertyValue("mapperHelperBeanName", mapperHelperRef); } else if (properties != null && properties.length > 0) { builder.addPropertyValue("mapperProperties", properties); } else { try { builder.addPropertyValue("mapperProperties", this.environment); } catch (Exception e) { LOGGER.warn("只有 Spring Boot 环境中可以通过 Environment(配置文件,环境变量,运行参数等方式) 配置通用 Mapper," + "其他环境请通过 @MapperScan 注解中的 mapperHelperRef 或 properties 参数进行配置!" + "如果你使用 tk.mybatis.mapper.session.Configuration 配置的通用 Mapper,你可以忽略该错误!", e); } } var lazyInitialization = annoAttrs.getString("lazyInitialization"); if (StringUtils.hasText(lazyInitialization)) { builder.addPropertyValue("lazyInitialization", lazyInitialization); } var defaultScope = annoAttrs.getString("defaultScope"); if (!AbstractBeanDefinition.SCOPE_DEFAULT.equals(defaultScope)) { builder.addPropertyValue("defaultScope", defaultScope); } builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); // for spring-native builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); } /** * Parse excludeFilters which FilterType is REGEX or ASPECTJ * * @param filterAttributes * AnnotationAttributes of excludeFilters * * @since 3.0.3 */ private List> parseFiltersHasPatterns(AnnotationAttributes filterAttributes) { List> rawTypeFilters = new ArrayList<>(); FilterType filterType = filterAttributes.getEnum("type"); var expressionArray = filterAttributes.getStringArray("pattern"); for (String expression : expressionArray) { switch (filterType) { case REGEX: case ASPECTJ: Map typeFilter = new HashMap<>(16); typeFilter.put("type", filterType.name().toLowerCase()); typeFilter.put("expression", expression); rawTypeFilters.add(typeFilter); break; default: throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType + " FilterType in exclude filter of @MapperScan"); } } return rawTypeFilters; } /** * Parse excludeFilters which FilterType is ANNOTATION ASSIGNABLE or CUSTOM * * @param filterAttributes * AnnotationAttributes of excludeFilters * * @since 3.0.3 */ private List typeFiltersFor(AnnotationAttributes filterAttributes) { List typeFilters = new ArrayList<>(); FilterType filterType = filterAttributes.getEnum("type"); for (Class filterClass : filterAttributes.getClassArray("value")) { switch (filterType) { case ANNOTATION: Assert.isAssignable(Annotation.class, filterClass, "Specified an unsupported type in 'ANNOTATION' exclude filter of @MapperScan"); @SuppressWarnings("unchecked") var annoClass = (Class) filterClass; typeFilters.add(new AnnotationTypeFilter(annoClass)); break; case ASSIGNABLE_TYPE: typeFilters.add(new AssignableTypeFilter(filterClass)); break; case CUSTOM: Assert.isAssignable(TypeFilter.class, filterClass, "An error occured when processing a @ComponentScan " + "CUSTOM type filter: "); typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); break; default: throw new IllegalArgumentException("Cannot specify the 'value' or 'classes' attribute if use the " + filterType + " FilterType in exclude filter of @MapperScan"); } } return typeFilters; } private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) { return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index; } private static String getDefaultBasePackage(AnnotationMetadata importingClassMetadata) { return ClassUtils.getPackageName(importingClassMetadata.getClassName()); } /** * A {@link MapperScannerRegistrar} for {@link MapperScans}. * * @since 2.0.0 */ static class RepeatingRegistrar extends MapperScannerRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { var mapperScansAttrs = AnnotationAttributes .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScans.class.getName())); if (mapperScansAttrs != null) { var annotations = mapperScansAttrs.getAnnotationArray("value"); for (var i = 0; i < annotations.length; i++) { registerBeanDefinitions(importingClassMetadata, annotations[i], registry, generateBaseBeanName(importingClassMetadata, i)); } } } } } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java ================================================ /* * Copyright 2010-2022 the original author or authors. * * 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 * * https://www.apache.org/licenses/LICENSE-2.0 * * 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 tk.mybatis.spring.annotation; import org.springframework.context.annotation.Import; import java.lang.annotation.*; /** * The Container annotation that aggregates several {@link tk.mybatis.spring.annotation.MapperScan} annotations. *

* Can be used natively, declaring several nested {@link tk.mybatis.spring.annotation.MapperScan} annotations. Can also be used in conjunction with * Java 8's support for repeatable annotations, where {@link tk.mybatis.spring.annotation.MapperScan} can simply be declared several times on the * same method, implicitly generating this container annotation. * * @author Kazuki Shimizu * * @since 2.0.0 * * @see tk.mybatis.spring.annotation.MapperScan */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.RepeatingRegistrar.class) public @interface MapperScans { MapperScan[] value(); } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/mapper/ClassPathMapperScanner.java ================================================ /* * Copyright 2010-2024 the original author or authors. * * 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 * * https://www.apache.org/licenses/LICENSE-2.0 * * 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 tk.mybatis.spring.mapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.scope.ScopedProxyFactoryBean; import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.aot.AotDetector; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.core.NativeDetector; import org.springframework.core.env.Environment; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.StringUtils; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.lang.annotation.Annotation; import java.util.*; /** * A {@link ClassPathBeanDefinitionScanner} that registers Mappers by {@code basePackage}, {@code annotationClass}, or * {@code markerInterface}. If an {@code annotationClass} and/or {@code markerInterface} is specified, only the * specified types will be searched (searching for all interfaces will be disabled). *

* This functionality was previously a private class of {@link MapperScannerConfigurer}, but was broken out in version * 1.2.0. * * @author Hunter Presnall * @author Eduardo Macarron * * @see MapperFactoryBean * * @since 1.2.0 */ public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner { private static final Logger LOGGER = LoggerFactory.getLogger(ClassPathMapperScanner.class); // Copy of FactoryBean#OBJECT_TYPE_ATTRIBUTE which was added in Spring 5.2 static final String FACTORY_BEAN_OBJECT_TYPE = "factoryBeanObjectType"; private boolean addToConfig = true; private boolean lazyInitialization; private boolean printWarnLogIfNotFoundMappers = true; private SqlSessionFactory sqlSessionFactory; private SqlSessionTemplate sqlSessionTemplate; private String sqlSessionTemplateBeanName; private String sqlSessionFactoryBeanName; private Class annotationClass; private Class markerInterface; private MapperHelper mapperHelper; private String mapperHelperBeanName; private Class mapperFactoryBeanClass = MapperFactoryBean.class; private String defaultScope; private List excludeFilters; public ClassPathMapperScanner(BeanDefinitionRegistry registry, Environment environment) { super(registry, false, environment); setIncludeAnnotationConfig(!AotDetector.useGeneratedArtifacts()); setPrintWarnLogIfNotFoundMappers(!NativeDetector.inNativeImage()); } /** * @deprecated Please use the {@link #ClassPathMapperScanner(BeanDefinitionRegistry, Environment)}. */ @Deprecated(since = "3.0.4", forRemoval = true) public ClassPathMapperScanner(BeanDefinitionRegistry registry) { super(registry, false); setIncludeAnnotationConfig(!AotDetector.useGeneratedArtifacts()); setPrintWarnLogIfNotFoundMappers(!NativeDetector.inNativeImage()); } public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } public void setAnnotationClass(Class annotationClass) { this.annotationClass = annotationClass; } /** * Set whether enable lazy initialization for mapper bean. *

* Default is {@code false}. *

* * @param lazyInitialization * Set the @{code true} to enable * * @since 2.0.2 */ public void setLazyInitialization(boolean lazyInitialization) { this.lazyInitialization = lazyInitialization; } /** * Set whether print warning log if not found mappers that matches conditions. *

* Default is {@code true}. But {@code false} when running in native image. *

* * @param printWarnLogIfNotFoundMappers * Set the @{code true} to print * * @since 3.0.1 */ public void setPrintWarnLogIfNotFoundMappers(boolean printWarnLogIfNotFoundMappers) { this.printWarnLogIfNotFoundMappers = printWarnLogIfNotFoundMappers; } public void setMarkerInterface(Class markerInterface) { this.markerInterface = markerInterface; } public void setExcludeFilters(List excludeFilters) { this.excludeFilters = excludeFilters; } public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } public void setSqlSessionTemplateBeanName(String sqlSessionTemplateBeanName) { this.sqlSessionTemplateBeanName = sqlSessionTemplateBeanName; } public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) { this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName; } /** * @deprecated Since 2.0.1, Please use the {@link #setMapperFactoryBeanClass(Class)}. */ @Deprecated public void setMapperFactoryBean(MapperFactoryBean mapperFactoryBean) { this.mapperFactoryBeanClass = mapperFactoryBean == null ? MapperFactoryBean.class : mapperFactoryBean.getClass(); } /** * Set the {@code MapperFactoryBean} class. * * @param mapperFactoryBeanClass * the {@code MapperFactoryBean} class * * @since 2.0.1 */ public void setMapperFactoryBeanClass(Class mapperFactoryBeanClass) { this.mapperFactoryBeanClass = mapperFactoryBeanClass == null ? MapperFactoryBean.class : mapperFactoryBeanClass; } /** * Set the default scope of scanned mappers. *

* Default is {@code null} (equiv to singleton). *

* * @param defaultScope * the scope * * @since 2.0.6 */ public void setDefaultScope(String defaultScope) { this.defaultScope = defaultScope; } /** * Configures parent scanner to search for the right interfaces. It can search for all interfaces or just for those * that extends a markerInterface or/and those annotated with the annotationClass */ public void registerFilters() { var acceptAllInterfaces = true; // if specified, use the given annotation and / or marker interface if (this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter(this.annotationClass)); acceptAllInterfaces = false; } // override AssignableTypeFilter to ignore matches on the actual marker interface if (this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter(this.markerInterface) { @Override protected boolean matchClassName(String className) { return false; } }); acceptAllInterfaces = false; } if (acceptAllInterfaces) { // default include filter that accepts all classes addIncludeFilter((metadataReader, metadataReaderFactory) -> true); } // exclude package-info.java addExcludeFilter((metadataReader, metadataReaderFactory) -> { var className = metadataReader.getClassMetadata().getClassName(); if (className.endsWith("package-info")) { return true; } return metadataReader.getAnnotationMetadata() .hasAnnotation("tk.mybatis.mapper.annotation.RegisterMapper"); }); // exclude types declared by MapperScan.excludeFilters if (excludeFilters != null && excludeFilters.size() > 0) { for (TypeFilter excludeFilter : excludeFilters) { addExcludeFilter(excludeFilter); } } } /** * Calls the parent search that will search and register all the candidates. Then the registered objects are post * processed to set them as MapperFactoryBeans */ @Override public Set doScan(String... basePackages) { var beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { if (printWarnLogIfNotFoundMappers) { LOGGER.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } } else { processBeanDefinitions(beanDefinitions); } return beanDefinitions; } private void processBeanDefinitions(Set beanDefinitions) { AbstractBeanDefinition definition; var registry = getRegistry(); for (BeanDefinitionHolder holder : beanDefinitions) { definition = (AbstractBeanDefinition) holder.getBeanDefinition(); var scopedProxy = false; if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) { definition = (AbstractBeanDefinition) Optional .ofNullable(((RootBeanDefinition) definition).getDecoratedDefinition()) .map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> new IllegalStateException( "The target bean definition of scoped proxy bean not found. Root bean definition[" + holder + "]")); scopedProxy = true; } var beanClassName = definition.getBeanClassName(); LOGGER.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface"); // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59 try { Class beanClass = Resources.classForName(beanClassName); // Attribute for MockitoPostProcessor // https://github.com/mybatis/spring-boot-starter/issues/475 definition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, beanClass); // for spring-native definition.getPropertyValues().add("mapperInterface", beanClass); } catch (ClassNotFoundException ignore) { // ignore } definition.setBeanClass(this.mapperFactoryBeanClass); //设置通用 Mapper if (StringUtils.hasText(this.mapperHelperBeanName)) { definition.getPropertyValues().add("mapperHelper", new RuntimeBeanReference(this.mapperHelperBeanName)); } else { //不做任何配置的时候使用默认方式 if (this.mapperHelper == null) { this.mapperHelper = new MapperHelper(); } definition.getPropertyValues().add("mapperHelper", this.mapperHelper); } definition.getPropertyValues().add("addToConfig", this.addToConfig); var explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { LOGGER.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { LOGGER.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { LOGGER.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } definition.setLazyInit(lazyInitialization); if (scopedProxy) { continue; } if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(definition.getScope()) && defaultScope != null) { definition.setScope(defaultScope); } if (!definition.isSingleton()) { var proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true); if (registry.containsBeanDefinition(proxyHolder.getBeanName())) { registry.removeBeanDefinition(proxyHolder.getBeanName()); } registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition()); } } } @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); } @Override protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) { if (super.checkCandidate(beanName, beanDefinition)) { return true; } LOGGER.warn("Skipping MapperFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!"); return false; } public MapperHelper getMapperHelper() { return mapperHelper; } public void setMapperHelper(MapperHelper mapperHelper) { this.mapperHelper = mapperHelper; } /** * 配置通用 Mapper * * @param config */ public void setConfig(Config config) { if (mapperHelper == null) { mapperHelper = new MapperHelper(); } mapperHelper.setConfig(config); } public void setMapperHelperBeanName(String mapperHelperBeanName) { this.mapperHelperBeanName = mapperHelperBeanName; } /** * TODO 从环境变量中获取 mapper 配置信息 * * @param environment */ public void setMapperProperties(Environment environment) { Config config = SpringBootBindUtil.bind(environment, Config.class, Config.PREFIX); if (mapperHelper == null) { mapperHelper = new MapperHelper(); } if (config != null) { mapperHelper.setConfig(config); } } /** * TODO 从 properties 数组获取 mapper 配置信息 * * @param properties */ public void setMapperProperties(String[] properties) { if (mapperHelper == null) { mapperHelper = new MapperHelper(); } Properties props = new Properties(); for (String property : properties) { property = property.trim(); int index = property.indexOf("="); if (index < 0) { throw new MapperException("通过 @MapperScan 注解的 properties 参数配置出错:" + property + " !\n" + "请保证配置项按 properties 文件格式要求进行配置,例如:\n" + "properties = {\n" + "\t\"mappers=tk.mybatis.mapper.common.Mapper\",\n" + "\t\"notEmpty=true\"\n" + "}" ); } props.put(property.substring(0, index).trim(), property.substring(index + 1).trim()); } mapperHelper.setProperties(props); } } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/mapper/MapperFactoryBean.java ================================================ /** * Copyright 2010-2016 the original author or authors. *

* 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 *

* http://www.apache.org/licenses/LICENSE-2.0 *

* 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 tk.mybatis.spring.mapper; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.session.Configuration; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.support.SqlSessionDaoSupport; import org.springframework.beans.factory.FactoryBean; import tk.mybatis.mapper.mapperhelper.MapperHelper; import static org.springframework.util.Assert.notNull; /** * BeanFactory that enables injection of MyBatis mapper interfaces. It can be set up with a * SqlSessionFactory or a pre-configured SqlSessionTemplate. *

* Sample configuration: *

*

 * {@code
 * 
 * 
 * 
 * 

* * * *

* * * * } *

*

* Note that this factory can only inject interfaces, not concrete classes. * * @author Eduardo Macarron * @author liuzh * @see SqlSessionTemplate */ public class MapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean { private Class mapperInterface; private boolean addToConfig = true; private MapperHelper mapperHelper; public MapperFactoryBean() { //intentionally empty } public MapperFactoryBean(Class mapperInterface) { this.mapperInterface = mapperInterface; } /** * {@inheritDoc} */ @Override protected void checkDaoConfig() { super.checkDaoConfig(); notNull(this.mapperInterface, "Property 'mapperInterface' is required"); Configuration configuration = getSqlSession().getConfiguration(); if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { try { configuration.addMapper(this.mapperInterface); } catch (Exception e) { logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e); throw new IllegalArgumentException(e); } finally { ErrorContext.instance().reset(); } } //直接针对接口处理通用接口方法对应的 MappedStatement 是安全的,通用方法不会出现 IncompleteElementException 的情况 if (configuration.hasMapper(this.mapperInterface) && mapperHelper != null && mapperHelper.isExtendCommonMapper(this.mapperInterface)) { mapperHelper.processConfiguration(getSqlSession().getConfiguration(), this.mapperInterface); } } /** * Return the mapper interface of the MyBatis mapper * * @return class of the interface */ public Class getMapperInterface() { return mapperInterface; } /** * Sets the mapper interface of the MyBatis mapper * * @param mapperInterface class of the interface */ public void setMapperInterface(Class mapperInterface) { this.mapperInterface = mapperInterface; } /** * {@inheritDoc} */ @Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); } //------------- mutators -------------- /** * {@inheritDoc} */ @Override public Class getObjectType() { return this.mapperInterface; } /** * Return the flag for addition into MyBatis config. * * @return true if the mapper will be added to MyBatis in the case it is not already * registered. */ public boolean isAddToConfig() { return addToConfig; } /** * If addToConfig is false the mapper will not be added to MyBatis. This means * it must have been included in mybatis-config.xml. *

* If it is true, the mapper will be added to MyBatis in the case it is not already * registered. *

* By default addToCofig is true. * * @param addToConfig */ public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } /** * 设置通用 Mapper 配置 * * @param mapperHelper */ public void setMapperHelper(MapperHelper mapperHelper) { this.mapperHelper = mapperHelper; } /** * {@inheritDoc} */ @Override public boolean isSingleton() { return true; } } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/mapper/MapperScannerConfigurer.java ================================================ /* * Copyright 2010-2024 the original author or authors. * * 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 * * https://www.apache.org/licenses/LICENSE-2.0 * * 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 tk.mybatis.spring.mapper; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.BeanUtils; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PropertyResourceConfigurer; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; import org.springframework.core.type.filter.*; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.common.Marker; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.lang.annotation.Annotation; import java.util.*; import java.util.regex.Pattern; import static org.springframework.util.Assert.notNull; /** * BeanDefinitionRegistryPostProcessor that searches recursively starting from a base package for interfaces and * registers them as {@code MapperFactoryBean}. Note that only interfaces with at least one method will be registered; * concrete classes will be ignored. *

* This class was a {code BeanFactoryPostProcessor} until 1.0.1 version. It changed to * {@code BeanDefinitionRegistryPostProcessor} in 1.0.2. See https://jira.springsource.org/browse/SPR-8269 for the * details. *

* The {@code basePackage} property can contain more than one package name, separated by either commas or semicolons. *

* This class supports filtering the mappers created by either specifying a marker interface or an annotation. The * {@code annotationClass} property specifies an annotation to search for. The {@code markerInterface} property * specifies a parent interface to search for. If both properties are specified, mappers are added for interfaces that * match either criteria. By default, these two properties are null, so all interfaces in the given * {@code basePackage} are added as mappers. *

* This configurer enables autowire for all the beans that it creates so that they are automatically autowired with the * proper {@code SqlSessionFactory} or {@code SqlSessionTemplate}. If there is more than one {@code SqlSessionFactory} * in the application, however, autowiring cannot be used. In this case you must explicitly specify either an * {@code SqlSessionFactory} or an {@code SqlSessionTemplate} to use via the bean name properties. Bean names * are used rather than actual objects because Spring does not initialize property placeholders until after this class * is processed. *

* Passing in an actual object which may require placeholders (i.e. DB user password) will fail. Using bean names defers * actual object creation until later in the startup process, after all placeholder substitution is completed. However, * note that this configurer does support property placeholders of its own properties. The * basePackage and bean name properties all support ${property} style substitution. *

* Configuration sample: * *

 * {@code
 *   
 *       
 *       
 *       
 *   
 * }
 * 
* * @author Hunter Presnall * @author Eduardo Macarron * * @see MapperFactoryBean * @see ClassPathMapperScanner */ public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { private String basePackage; private boolean addToConfig = true; private String lazyInitialization; private SqlSessionFactory sqlSessionFactory; private SqlSessionTemplate sqlSessionTemplate; private String sqlSessionFactoryBeanName; private String sqlSessionTemplateBeanName; private Class annotationClass; private Class markerInterface; private List excludeFilters; private List> rawExcludeFilters; private Class mapperFactoryBeanClass; private ApplicationContext applicationContext; private String beanName; private boolean processPropertyPlaceHolders; private BeanNameGenerator nameGenerator; private String defaultScope; private MapperHelper mapperHelper = new MapperHelper(); private String mapperHelperBeanName; public MapperHelper getMapperHelper() { return mapperHelper; } public void setMapperHelper(MapperHelper mapperHelper) { this.mapperHelper = mapperHelper; } /** * This property lets you set the base package for your mapper interface files. *

* You can set more than one package by using a semicolon or comma as a separator. *

* Mappers will be searched for recursively starting in the specified package(s). * * @param basePackage * base package name */ public void setBasePackage(String basePackage) { this.basePackage = basePackage; } /** * Same as {@code MapperFactoryBean#setAddToConfig(boolean)}. * * @param addToConfig * a flag that whether add mapper to MyBatis or not * * @see MapperFactoryBean#setAddToConfig(boolean) */ public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } /** * Set whether enable lazy initialization for mapper bean. *

* Default is {@code false}. *

* * @param lazyInitialization * Set the @{code true} to enable * * @since 2.0.2 */ public void setLazyInitialization(String lazyInitialization) { this.lazyInitialization = lazyInitialization; } /** * This property specifies the annotation that the scanner will search for. *

* The scanner will register all interfaces in the base package that also have the specified annotation. *

* Note this can be combined with markerInterface. * * @param annotationClass * annotation class */ public void setAnnotationClass(Class annotationClass) { this.annotationClass = annotationClass; } /** * This property specifies the parent that the scanner will search for. *

* The scanner will register all interfaces in the base package that also have the specified interface class as a * parent. *

* Note this can be combined with annotationClass. * * @param superClass * parent class */ public void setMarkerInterface(Class superClass) { this.markerInterface = superClass; if (Marker.class.isAssignableFrom(superClass)) { mapperHelper.registerMapper(superClass); } } /** * Specifies which types are not eligible for the mapper scanner. *

* The scanner will exclude types that define with excludeFilters. * * @since 3.0.3 * * @param excludeFilters * list of TypeFilter */ public void setExcludeFilters(List excludeFilters) { this.excludeFilters = excludeFilters; } /** * In order to support process PropertyPlaceHolders. *

* After parsed, it will be added to excludeFilters. * * @since 3.0.3 * * @param rawExcludeFilters * list of rawExcludeFilter */ public void setRawExcludeFilters(List> rawExcludeFilters) { this.rawExcludeFilters = rawExcludeFilters; } /** * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. *

* * @deprecated Use {@link #setSqlSessionTemplateBeanName(String)} instead * * @param sqlSessionTemplate * a template of SqlSession */ @Deprecated public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } /** * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. *

* Note bean names are used, not bean references. This is because the scanner loads early during the start process and * it is too early to build mybatis object instances. * * @since 1.1.0 * * @param sqlSessionTemplateName * Bean name of the {@code SqlSessionTemplate} */ public void setSqlSessionTemplateBeanName(String sqlSessionTemplateName) { this.sqlSessionTemplateBeanName = sqlSessionTemplateName; } /** * 属性注入 * * @param properties */ public void setProperties(Properties properties) { mapperHelper.setProperties(properties); } /** * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. *

* * @deprecated Use {@link #setSqlSessionFactoryBeanName(String)} instead. * * @param sqlSessionFactory * a factory of SqlSession */ @Deprecated public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } /** * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. *

* Note bean names are used, not bean references. This is because the scanner loads early during the start process and * it is too early to build mybatis object instances. * * @since 1.1.0 * * @param sqlSessionFactoryName * Bean name of the {@code SqlSessionFactory} */ public void setSqlSessionFactoryBeanName(String sqlSessionFactoryName) { this.sqlSessionFactoryBeanName = sqlSessionFactoryName; } /** * Specifies a flag that whether execute a property placeholder processing or not. *

* The default is {@literal false}. This means that a property placeholder processing does not execute. * * @since 1.1.1 * * @param processPropertyPlaceHolders * a flag that whether execute a property placeholder processing or not */ public void setProcessPropertyPlaceHolders(boolean processPropertyPlaceHolders) { this.processPropertyPlaceHolders = processPropertyPlaceHolders; } /** * The class of the {@link MapperFactoryBean} to return a mybatis proxy as spring bean. * * @param mapperFactoryBeanClass * The class of the MapperFactoryBean * * @since 2.0.1 */ public void setMapperFactoryBeanClass(Class mapperFactoryBeanClass) { this.mapperFactoryBeanClass = mapperFactoryBeanClass; } @Override public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public void setBeanName(String name) { this.beanName = name; } /** * Gets beanNameGenerator to be used while running the scanner. * * @return the beanNameGenerator BeanNameGenerator that has been configured * * @since 1.2.0 */ public BeanNameGenerator getNameGenerator() { return nameGenerator; } /** * Sets beanNameGenerator to be used while running the scanner. * * @param nameGenerator * the beanNameGenerator to set * * @since 1.2.0 */ public void setNameGenerator(BeanNameGenerator nameGenerator) { this.nameGenerator = nameGenerator; } /** * Sets the default scope of scanned mappers. *

* Default is {@code null} (equiv to singleton). *

* * @param defaultScope * the default scope * * @since 2.0.6 */ public void setDefaultScope(String defaultScope) { this.defaultScope = defaultScope; } @Override public void afterPropertiesSet() throws Exception { notNull(this.basePackage, "Property 'basePackage' is required"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // left intentionally blank } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { if (this.processPropertyPlaceHolders) { processPropertyPlaceHolders(); } var scanner = new ClassPathMapperScanner(registry, getEnvironment()); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setExcludeFilters(this.excludeFilters = mergeExcludeFilters()); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass); if (StringUtils.hasText(lazyInitialization)) { scanner.setLazyInitialization(Boolean.parseBoolean(lazyInitialization)); } if (StringUtils.hasText(defaultScope)) { scanner.setDefaultScope(defaultScope); } if (StringUtils.hasText(mapperHelperBeanName)) { scanner.setMapperHelperBeanName(mapperHelperBeanName); } scanner.registerFilters(); //设置通用 Mapper scanner.setMapperHelper(this.mapperHelper); scanner.scan( StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); } /* * BeanDefinitionRegistries are called early in application startup, before BeanFactoryPostProcessors. This means that * PropertyResourceConfigurers will not have been loaded and any property substitution of this class' properties will * fail. To avoid this, find any PropertyResourceConfigurers defined in the context and run them on this class' bean * definition. Then update the values. */ private void processPropertyPlaceHolders() { Map prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class, false, false); if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) { var mapperScannerBean = ((ConfigurableApplicationContext) applicationContext).getBeanFactory() .getBeanDefinition(beanName); // PropertyResourceConfigurer does not expose any methods to explicitly perform // property placeholder substitution. Instead, create a BeanFactory that just // contains this mapper scanner and post process the factory. var factory = new DefaultListableBeanFactory(); factory.registerBeanDefinition(beanName, mapperScannerBean); for (PropertyResourceConfigurer prc : prcs.values()) { prc.postProcessBeanFactory(factory); } PropertyValues values = mapperScannerBean.getPropertyValues(); this.basePackage = getPropertyValue("basePackage", values); this.sqlSessionFactoryBeanName = getPropertyValue("sqlSessionFactoryBeanName", values); this.sqlSessionTemplateBeanName = getPropertyValue("sqlSessionTemplateBeanName", values); this.lazyInitialization = getPropertyValue("lazyInitialization", values); this.defaultScope = getPropertyValue("defaultScope", values); this.rawExcludeFilters = getPropertyValueForTypeFilter("rawExcludeFilters", values); } this.basePackage = Optional.ofNullable(this.basePackage).map(getEnvironment()::resolvePlaceholders).orElse(null); this.sqlSessionFactoryBeanName = Optional.ofNullable(this.sqlSessionFactoryBeanName) .map(getEnvironment()::resolvePlaceholders).orElse(null); this.sqlSessionTemplateBeanName = Optional.ofNullable(this.sqlSessionTemplateBeanName) .map(getEnvironment()::resolvePlaceholders).orElse(null); this.lazyInitialization = Optional.ofNullable(this.lazyInitialization).map(getEnvironment()::resolvePlaceholders) .orElse(null); this.defaultScope = Optional.ofNullable(this.defaultScope).map(getEnvironment()::resolvePlaceholders).orElse(null); } private Environment getEnvironment() { return this.applicationContext.getEnvironment(); } private String getPropertyValue(String propertyName, PropertyValues values) { var property = values.getPropertyValue(propertyName); if (property == null) { return null; } var value = property.getValue(); if (value == null) { return null; } if (value instanceof String) { return value.toString(); } if (value instanceof TypedStringValue) { return ((TypedStringValue) value).getValue(); } return null; } @SuppressWarnings("unchecked") private List> getPropertyValueForTypeFilter(String propertyName, PropertyValues values) { var property = values.getPropertyValue(propertyName); Object value; if (property == null || (value = property.getValue()) == null || !(value instanceof List)) { return null; } return (List>) value; } private List mergeExcludeFilters() { List typeFilters = new ArrayList<>(); if (this.rawExcludeFilters == null || this.rawExcludeFilters.isEmpty()) { return this.excludeFilters; } if (this.excludeFilters != null && !this.excludeFilters.isEmpty()) { typeFilters.addAll(this.excludeFilters); } try { for (Map typeFilter : this.rawExcludeFilters) { typeFilters.add( createTypeFilter(typeFilter.get("type"), typeFilter.get("expression"), this.getClass().getClassLoader())); } } catch (ClassNotFoundException exception) { throw new RuntimeException("ClassNotFoundException occur when to load the Specified excludeFilter classes.", exception); } return typeFilters; } @SuppressWarnings("unchecked") private TypeFilter createTypeFilter(String filterType, String expression, @Nullable ClassLoader classLoader) throws ClassNotFoundException { if (this.processPropertyPlaceHolders) { expression = this.getEnvironment().resolvePlaceholders(expression); } switch (filterType) { case "annotation": Class filterAnno = ClassUtils.forName(expression, classLoader); if (!Annotation.class.isAssignableFrom(filterAnno)) { throw new IllegalArgumentException( "Class is not assignable to [" + Annotation.class.getName() + "]: " + expression); } return new AnnotationTypeFilter((Class) filterAnno); case "custom": Class filterClass = ClassUtils.forName(expression, classLoader); if (!TypeFilter.class.isAssignableFrom(filterClass)) { throw new IllegalArgumentException( "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); } return (TypeFilter) BeanUtils.instantiateClass(filterClass); case "assignable": return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader)); case "regex": return new RegexPatternTypeFilter(Pattern.compile(expression)); case "aspectj": return new AspectJTypeFilter(expression, classLoader); default: throw new IllegalArgumentException("Unsupported filter type: " + filterType); } } public void setMapperHelperBeanName(String mapperHelperBeanName) { this.mapperHelperBeanName = mapperHelperBeanName; } /** * 从环境变量中获取 mapper 配置信息 * * @param environment */ public void setMapperProperties(Environment environment) { Config config = SpringBootBindUtil.bind(environment, Config.class, Config.PREFIX); if (mapperHelper == null) { mapperHelper = new MapperHelper(); } if (config != null) { mapperHelper.setConfig(config); } } /** * 从 properties 数组获取 mapper 配置信息 * * @param properties */ public void setMapperProperties(String[] properties) { if (mapperHelper == null) { mapperHelper = new MapperHelper(); } Properties props = new Properties(); for (String property : properties) { property = property.trim(); int index = property.indexOf("="); if (index < 0) { throw new MapperException("通过 @MapperScan 注解的 properties 参数配置出错:" + property + " !\n" + "请保证配置项按 properties 文件格式要求进行配置,例如:\n" + "properties = {\n" + "\t\"mappers=tk.mybatis.mapper.common.Mapper\",\n" + "\t\"notEmpty=true\"\n" + "}" ); } props.put(property.substring(0, index).trim(), property.substring(index + 1).trim()); } mapperHelper.setProperties(props); } } ================================================ FILE: spring/src/main/java/tk/mybatis/spring/mapper/SpringBootBindUtil.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2018 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.spring.mapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import java.lang.reflect.Method; /** * @author liuzh * @since 1.2.1 */ public abstract class SpringBootBindUtil { private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootBindUtil.class); public static T bind(Environment environment, Class targetClass, String prefix) { try { Class binderClass = Class.forName("org.springframework.boot.context.properties.bind.Binder"); Method getMethod = binderClass.getDeclaredMethod("get", Environment.class); Method bindMethod = binderClass.getDeclaredMethod("bind", String.class, Class.class); Object binder = getMethod.invoke(null, environment); Object bindResult = bindMethod.invoke(binder, prefix, targetClass); // Check if the value is bound Method isBoundMethod = bindResult.getClass().getDeclaredMethod("isBound"); boolean isBound = (boolean) isBoundMethod.invoke(bindResult); if (isBound) { Method getMethodResult = bindResult.getClass().getDeclaredMethod("get"); return (T) getMethodResult.invoke(bindResult); } else { return null; } } catch (Exception e) { LOGGER.warn("Bind " + targetClass + " error", e); return null; } } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/annotation/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.annotation; import jakarta.persistence.Id; import java.io.Serializable; public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String countryname; private String countrycode; public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/annotation/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.annotation; import tk.mybatis.mapper.common.Mapper; public interface CountryMapper extends Mapper { } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/annotation/SpringAnnotationTest.java ================================================ package tk.mybatis.mapper.annotation; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.spring.annotation.MapperScan; import javax.sql.DataSource; import java.util.ArrayList; import java.util.List; /** * @author liuzh */ public class SpringAnnotationTest { private AnnotationConfigApplicationContext applicationContext; @Before public void setupContext() { applicationContext = new AnnotationConfigApplicationContext(); } private void startContext() { applicationContext.refresh(); applicationContext.start(); // this will throw an exception if the beans cannot be found applicationContext.getBean("sqlSessionFactory"); } @Test public void testMyBatisConfigRef() { applicationContext.register(MyBatisConfigRef.class); startContext(); CountryMapper countryMapper = applicationContext.getBean(CountryMapper.class); List countries = countryMapper.selectAll(); Assert.assertNotNull(countries); Assert.assertEquals(183, countries.size()); } @Test public void testMyBatisConfigProperties() { applicationContext.register(MyBatisConfigProperties.class); startContext(); CountryMapper countryMapper = applicationContext.getBean(CountryMapper.class); List countries = countryMapper.selectAll(); Assert.assertNotNull(countries); Assert.assertEquals(183, countries.size()); } @Test public void testMyBatisConfiguration() { applicationContext.register(MyBatisConfiguration.class); startContext(); CountryMapper countryMapper = applicationContext.getBean(CountryMapper.class); List countries = countryMapper.selectAll(); Assert.assertNotNull(countries); Assert.assertEquals(183, countries.size()); } @Test(expected = Exception.class) public void testMyBatisConfigPropertiesError() { applicationContext.register(MyBatisConfigPropertiesError.class); startContext(); CountryMapper countryMapper = applicationContext.getBean(CountryMapper.class); List countries = countryMapper.selectAll(); Assert.assertNotNull(countries); Assert.assertEquals(183, countries.size()); } @Configuration @MapperScan(value = "tk.mybatis.mapper.annotation", mapperHelperRef = "mapperHelper") public static class MyBatisConfigRef { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("tk/mybatis/mapper/xml/CreateDB.sql") .build(); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); return sessionFactory.getObject(); } @Bean public MapperHelper mapperHelper() { Config config = new Config(); List mappers = new ArrayList(); mappers.add(Mapper.class); config.setMappers(mappers); MapperHelper mapperHelper = new MapperHelper(); mapperHelper.setConfig(config); return mapperHelper; } } @Configuration @MapperScan(value = "tk.mybatis.mapper.annotation", properties = { "mappers=tk.mybatis.mapper.common.Mapper", "notEmpty=true" } ) public static class MyBatisConfigProperties { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("tk/mybatis/mapper/xml/CreateDB.sql") .build(); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); return sessionFactory.getObject(); } } @Configuration @MapperScan(value = "tk.mybatis.mapper.annotation", properties = { //参数配置错误 "mapperstk.mybatis.mapper.common.Mapper", "notEmpty=true" } ) public static class MyBatisConfigPropertiesError { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("tk/mybatis/mapper/xml/CreateDB.sql") .build(); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); return sessionFactory.getObject(); } } @Configuration @MapperScan(value = "tk.mybatis.mapper.annotation") public static class MyBatisConfiguration { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("tk/mybatis/mapper/xml/CreateDB.sql") .build(); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); tk.mybatis.mapper.session.Configuration configuration = new tk.mybatis.mapper.session.Configuration(); configuration.setMapperHelper(new MapperHelper()); sessionFactory.setConfiguration(configuration); return sessionFactory.getObject(); } } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/configuration/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.configuration; import jakarta.persistence.Id; import java.io.Serializable; public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String countryname; private String countrycode; public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/configuration/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.configuration; import org.apache.ibatis.annotations.CacheNamespace; import tk.mybatis.mapper.common.Mapper; @CacheNamespace public interface CountryMapper extends Mapper { } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/configuration/CreateDB.sql ================================================ drop table country if exists; create table country ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) DEFAULT 'HH', version INTEGER DEFAULT 1 NOT NULL ); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (13, 'Bahamas', 'BS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (14, 'Bahrain', 'BH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (15, 'Bangladesh', 'BD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (16, 'Barbados', 'BB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (17, 'Belarus', 'BY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (18, 'Belgium', 'BE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (19, 'Belize', 'BZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (20, 'Benin', 'BJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (21, 'Bermuda Is.', 'BM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (22, 'Bolivia', 'BO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (23, 'Botswana', 'BW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (24, 'Brazil', 'BR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (25, 'Brunei', 'BN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (26, 'Bulgaria', 'BG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (27, 'Burkina-faso', 'BF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (28, 'Burma', 'MM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (29, 'Burundi', 'BI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (30, 'Cameroon', 'CM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (31, 'Canada', 'CA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (32, 'Central African Republic', 'CF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (33, 'Chad', 'TD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (34, 'Chile', 'CL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (35, 'China', 'CN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (36, 'Colombia', 'CO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (37, 'Congo', 'CG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (38, 'Cook Is.', 'CK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (39, 'Costa Rica', 'CR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (40, 'Cuba', 'CU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (41, 'Cyprus', 'CY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (42, 'Czech Republic', 'CZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (43, 'Denmark', 'DK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (44, 'Djibouti', 'DJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (45, 'Dominica Rep.', 'DO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (46, 'Ecuador', 'EC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (47, 'Egypt', 'EG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (48, 'EI Salvador', 'SV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (49, 'Estonia', 'EE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (50, 'Ethiopia', 'ET', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (51, 'Fiji', 'FJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (52, 'Finland', 'FI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (53, 'France', 'FR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (54, 'French Guiana', 'GF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (55, 'Gabon', 'GA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (56, 'Gambia', 'GM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (57, 'Georgia', 'GE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (58, 'Germany', 'DE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (59, 'Ghana', 'GH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (60, 'Gibraltar', 'GI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (61, 'Greece', 'GR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (62, 'Grenada', 'GD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (63, 'Guam', 'GU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (64, 'Guatemala', 'GT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (65, 'Guinea', 'GN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (66, 'Guyana', 'GY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (67, 'Haiti', 'HT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (68, 'Honduras', 'HN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (69, 'Hongkong', 'HK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (70, 'Hungary', 'HU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (71, 'Iceland', 'IS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (72, 'India', 'IN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (73, 'Indonesia', 'ID', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (74, 'Iran', 'IR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (75, 'Iraq', 'IQ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (76, 'Ireland', 'IE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (77, 'Israel', 'IL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (78, 'Italy', 'IT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (79, 'Jamaica', 'JM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (80, 'Japan', 'JP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (81, 'Jordan', 'JO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (82, 'Kampuchea (Cambodia )', 'KH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (83, 'Kazakstan', 'KZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (84, 'Kenya', 'KE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (85, 'Korea', 'KR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (86, 'Kuwait', 'KW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (87, 'Kyrgyzstan', 'KG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (88, 'Laos', 'LA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (89, 'Latvia', 'LV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (90, 'Lebanon', 'LB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (91, 'Lesotho', 'LS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (92, 'Liberia', 'LR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (93, 'Libya', 'LY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (94, 'Liechtenstein', 'LI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (95, 'Lithuania', 'LT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (96, 'Luxembourg', 'LU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (97, 'Macao', 'MO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (98, 'Madagascar', 'MG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (99, 'Malawi', 'MW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (100, 'Malaysia', 'MY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (101, 'Maldives', 'MV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (102, 'Mali', 'ML', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (103, 'Malta', 'MT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (104, 'Mauritius', 'MU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (105, 'Mexico', 'MX', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (106, 'Moldova, Republic of', 'MD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (107, 'Monaco', 'MC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (108, 'Mongolia', 'MN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (109, 'Montserrat Is', 'MS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (110, 'Morocco', 'MA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (111, 'Mozambique', 'MZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (112, 'Namibia', 'NA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (113, 'Nauru', 'NR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (114, 'Nepal', 'NP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (115, 'Netherlands', 'NL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (116, 'New Zealand', 'NZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (117, 'Nicaragua', 'NI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (118, 'Niger', 'NE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (119, 'Nigeria', 'NG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (120, 'North Korea', 'KP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (121, 'Norway', 'NO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (122, 'Oman', 'OM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (123, 'Pakistan', 'PK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (124, 'Panama', 'PA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (125, 'Papua New Cuinea', 'PG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (126, 'Paraguay', 'PY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (127, 'Peru', 'PE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (128, 'Philippines', 'PH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (129, 'Poland', 'PL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (130, 'French Polynesia', 'PF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (131, 'Portugal', 'PT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (132, 'Puerto Rico', 'PR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (133, 'Qatar', 'QA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (134, 'Romania', 'RO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (135, 'Russia', 'RU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (136, 'Saint Lueia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (137, 'Saint Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (138, 'San Marino', 'SM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (139, 'Sao Tome and Principe', 'ST', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (140, 'Saudi Arabia', 'SA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (141, 'Senegal', 'SN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (142, 'Seychelles', 'SC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (143, 'Sierra Leone', 'SL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (144, 'Singapore', 'SG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (145, 'Slovakia', 'SK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (146, 'Slovenia', 'SI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (147, 'Solomon Is', 'SB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (148, 'Somali', 'SO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (149, 'South Africa', 'ZA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (150, 'Spain', 'ES', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (151, 'Sri Lanka', 'LK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (152, 'St.Lucia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (153, 'St.Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (154, 'Sudan', 'SD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (155, 'Suriname', 'SR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (156, 'Swaziland', 'SZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (157, 'Sweden', 'SE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (158, 'Switzerland', 'CH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (159, 'Syria', 'SY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (160, 'Taiwan', 'TW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (161, 'Tajikstan', 'TJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (162, 'Tanzania', 'TZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (163, 'Thailand', 'TH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (164, 'Togo', 'TG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (165, 'Tonga', 'TO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (166, 'Trinidad and Tobago', 'TT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (167, 'Tunisia', 'TN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (168, 'Turkey', 'TR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (169, 'Turkmenistan', 'TM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (170, 'Uganda', 'UG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (171, 'Ukraine', 'UA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (172, 'United Arab Emirates', 'AE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (173, 'United Kiongdom', 'GB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (174, 'United States of America', 'US', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (175, 'Uruguay', 'UY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (176, 'Uzbekistan', 'UZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (177, 'Venezuela', 'VE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (178, 'Vietnam', 'VN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (179, 'Yemen', 'YE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (180, 'Yugoslavia', 'YU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (181, 'Zimbabwe', 'ZW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (182, 'Zaire', 'ZR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (183, 'Zambia', 'ZM', 1); ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/configuration/SpringConfigTest.java ================================================ package tk.mybatis.mapper.configuration; import org.junit.Assert; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; /** * @author liuzh */ public class SpringConfigTest { private ClassPathXmlApplicationContext context; @Test public void testCountryMapper() { context = new ClassPathXmlApplicationContext("tk/mybatis/mapper/configuration/spring.xml"); CountryMapper countryMapper = context.getBean(CountryMapper.class); List countries = countryMapper.selectAll(); Assert.assertNotNull(countries); Assert.assertEquals(183, countries.size()); } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/configuration/spring.xml ================================================ notEmpty=true ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/xml/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.xml; import jakarta.persistence.Id; import java.io.Serializable; public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String countryname; private String countrycode; public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/xml/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.xml; import tk.mybatis.mapper.common.Mapper; public interface CountryMapper extends Mapper { } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/xml/CreateDB.sql ================================================ drop table country if exists; create table country ( id integer NOT NULL PRIMARY KEY, countryname varchar(32), countrycode VARCHAR(2) DEFAULT 'HH', version INTEGER DEFAULT 1 NOT NULL ); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (13, 'Bahamas', 'BS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (14, 'Bahrain', 'BH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (15, 'Bangladesh', 'BD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (16, 'Barbados', 'BB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (17, 'Belarus', 'BY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (18, 'Belgium', 'BE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (19, 'Belize', 'BZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (20, 'Benin', 'BJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (21, 'Bermuda Is.', 'BM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (22, 'Bolivia', 'BO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (23, 'Botswana', 'BW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (24, 'Brazil', 'BR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (25, 'Brunei', 'BN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (26, 'Bulgaria', 'BG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (27, 'Burkina-faso', 'BF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (28, 'Burma', 'MM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (29, 'Burundi', 'BI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (30, 'Cameroon', 'CM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (31, 'Canada', 'CA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (32, 'Central African Republic', 'CF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (33, 'Chad', 'TD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (34, 'Chile', 'CL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (35, 'China', 'CN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (36, 'Colombia', 'CO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (37, 'Congo', 'CG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (38, 'Cook Is.', 'CK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (39, 'Costa Rica', 'CR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (40, 'Cuba', 'CU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (41, 'Cyprus', 'CY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (42, 'Czech Republic', 'CZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (43, 'Denmark', 'DK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (44, 'Djibouti', 'DJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (45, 'Dominica Rep.', 'DO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (46, 'Ecuador', 'EC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (47, 'Egypt', 'EG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (48, 'EI Salvador', 'SV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (49, 'Estonia', 'EE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (50, 'Ethiopia', 'ET', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (51, 'Fiji', 'FJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (52, 'Finland', 'FI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (53, 'France', 'FR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (54, 'French Guiana', 'GF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (55, 'Gabon', 'GA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (56, 'Gambia', 'GM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (57, 'Georgia', 'GE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (58, 'Germany', 'DE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (59, 'Ghana', 'GH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (60, 'Gibraltar', 'GI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (61, 'Greece', 'GR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (62, 'Grenada', 'GD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (63, 'Guam', 'GU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (64, 'Guatemala', 'GT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (65, 'Guinea', 'GN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (66, 'Guyana', 'GY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (67, 'Haiti', 'HT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (68, 'Honduras', 'HN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (69, 'Hongkong', 'HK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (70, 'Hungary', 'HU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (71, 'Iceland', 'IS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (72, 'India', 'IN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (73, 'Indonesia', 'ID', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (74, 'Iran', 'IR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (75, 'Iraq', 'IQ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (76, 'Ireland', 'IE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (77, 'Israel', 'IL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (78, 'Italy', 'IT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (79, 'Jamaica', 'JM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (80, 'Japan', 'JP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (81, 'Jordan', 'JO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (82, 'Kampuchea (Cambodia )', 'KH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (83, 'Kazakstan', 'KZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (84, 'Kenya', 'KE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (85, 'Korea', 'KR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (86, 'Kuwait', 'KW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (87, 'Kyrgyzstan', 'KG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (88, 'Laos', 'LA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (89, 'Latvia', 'LV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (90, 'Lebanon', 'LB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (91, 'Lesotho', 'LS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (92, 'Liberia', 'LR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (93, 'Libya', 'LY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (94, 'Liechtenstein', 'LI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (95, 'Lithuania', 'LT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (96, 'Luxembourg', 'LU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (97, 'Macao', 'MO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (98, 'Madagascar', 'MG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (99, 'Malawi', 'MW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (100, 'Malaysia', 'MY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (101, 'Maldives', 'MV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (102, 'Mali', 'ML', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (103, 'Malta', 'MT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (104, 'Mauritius', 'MU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (105, 'Mexico', 'MX', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (106, 'Moldova, Republic of', 'MD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (107, 'Monaco', 'MC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (108, 'Mongolia', 'MN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (109, 'Montserrat Is', 'MS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (110, 'Morocco', 'MA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (111, 'Mozambique', 'MZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (112, 'Namibia', 'NA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (113, 'Nauru', 'NR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (114, 'Nepal', 'NP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (115, 'Netherlands', 'NL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (116, 'New Zealand', 'NZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (117, 'Nicaragua', 'NI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (118, 'Niger', 'NE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (119, 'Nigeria', 'NG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (120, 'North Korea', 'KP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (121, 'Norway', 'NO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (122, 'Oman', 'OM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (123, 'Pakistan', 'PK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (124, 'Panama', 'PA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (125, 'Papua New Cuinea', 'PG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (126, 'Paraguay', 'PY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (127, 'Peru', 'PE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (128, 'Philippines', 'PH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (129, 'Poland', 'PL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (130, 'French Polynesia', 'PF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (131, 'Portugal', 'PT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (132, 'Puerto Rico', 'PR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (133, 'Qatar', 'QA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (134, 'Romania', 'RO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (135, 'Russia', 'RU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (136, 'Saint Lueia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (137, 'Saint Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (138, 'San Marino', 'SM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (139, 'Sao Tome and Principe', 'ST', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (140, 'Saudi Arabia', 'SA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (141, 'Senegal', 'SN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (142, 'Seychelles', 'SC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (143, 'Sierra Leone', 'SL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (144, 'Singapore', 'SG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (145, 'Slovakia', 'SK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (146, 'Slovenia', 'SI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (147, 'Solomon Is', 'SB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (148, 'Somali', 'SO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (149, 'South Africa', 'ZA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (150, 'Spain', 'ES', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (151, 'Sri Lanka', 'LK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (152, 'St.Lucia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (153, 'St.Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (154, 'Sudan', 'SD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (155, 'Suriname', 'SR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (156, 'Swaziland', 'SZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (157, 'Sweden', 'SE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (158, 'Switzerland', 'CH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (159, 'Syria', 'SY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (160, 'Taiwan', 'TW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (161, 'Tajikstan', 'TJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (162, 'Tanzania', 'TZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (163, 'Thailand', 'TH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (164, 'Togo', 'TG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (165, 'Tonga', 'TO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (166, 'Trinidad and Tobago', 'TT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (167, 'Tunisia', 'TN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (168, 'Turkey', 'TR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (169, 'Turkmenistan', 'TM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (170, 'Uganda', 'UG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (171, 'Ukraine', 'UA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (172, 'United Arab Emirates', 'AE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (173, 'United Kiongdom', 'GB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (174, 'United States of America', 'US', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (175, 'Uruguay', 'UY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (176, 'Uzbekistan', 'UZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (177, 'Venezuela', 'VE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (178, 'Vietnam', 'VN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (179, 'Yemen', 'YE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (180, 'Yugoslavia', 'YU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (181, 'Zimbabwe', 'ZW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (182, 'Zaire', 'ZR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (183, 'Zambia', 'ZM', 1); ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/xml/SpringXmlTest.java ================================================ package tk.mybatis.mapper.xml; import org.junit.Assert; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; /** * @author liuzh */ public class SpringXmlTest { private ClassPathXmlApplicationContext context; @Test public void testCountryMapper() { context = new ClassPathXmlApplicationContext("tk/mybatis/mapper/xml/spring.xml"); CountryMapper countryMapper = context.getBean(CountryMapper.class); List countries = countryMapper.selectAll(); Assert.assertNotNull(countries); Assert.assertEquals(183, countries.size()); } } ================================================ FILE: spring/src/test/java/tk/mybatis/mapper/xml/spring.xml ================================================ ================================================ FILE: spring/src/test/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: spring-boot-starter/README.md ================================================ # MyBatis Mapper integration with Spring Boot [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-spring-boot-starter/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-spring-boot-starter) Mapper-Spring-Boot-Starter 帮助你集成通用 Mapper 到 Spring Boot。 Mapper-Spring-Boot-Starter will help you use Mapper with Spring Boot. ## How to use 在 pom.xml 中添加如下依赖: Add the following dependency to your pom.xml: ```xml tk.mybatis mapper-spring-boot-starter 1.2.3 ``` ## 1.2.3 - 2018-01-24 - 增加 `tk.mybatis.spring.mapper.SpringBootBindUtil`,使用原生方式兼容 Spring Boot 1.x 和 2.x 版本,已经不存在 relax 值问题,以前的配置不需要修改即可使用。 - 特别注意,如果使用了 `@MapperScan` 注解,请使用 `tk.mybatis.spring.annotation.MapperScan` 注解。 - 通用 Mapper 升级到 3.5.2 版本。 ## 1.2.2 - 由于 weekend 版本依赖问题,这个版本存在问题,不作为正式发布版本。 ## 1.2.1 - 2018-01-10 - 为了增强兼容性,`MapperAutoConfiguration` 增加 `@AutoConfigureBefore(name = "org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration")` 即使依赖中存在 MyBatis 的 starter,Mapper 也可以优先使用自动配置,MyBatis后续就不会触发生成 `@Bean` - 支持简单的 relax 绑定,例如 not-empty 会转换为 notEmpty 使用,兼容 spring boot 配置方式 ## 1.2.0 - 2018-01-08 - 通用 Mapper 3.5.0 - 去掉 mybatis-spring-boot-starter 依赖,不在使用 mybatis 官方 starter,使用通用 Mapper 时不要再引入官方 starter - 参考 mybatis 官方 starter 重新实现,解决 mapper 初始化可能存在的问题 [pr#5 by fengcbo](https://github.com/abel533/mapper-boot-starter/pull/5) - 如果需要使用 `@MapperScan` 请选择 tk 开头的 `tk.mybatis.spring.annotation.MapperScan` ## 1.1.7 - 2017-12-17 - 通用 Mapper 3.4.6 - spring-boot 1.5.9.RELEASE ## 1.1.6 - 2017-11-11 - 通用 Mapper 3.4.5 ## 1.1.5 - 2017-10-21 - 通用 Mapper 3.4.4 - mybatis-starter 1.3.1 - spring-boot 1.5.8.RELEASE ## 1.1.4 - 2017-08-18 - 通用 Mapper 3.4.3 ## 1.1.3 - 2017-07-18 - 通用 Mapper 3.4.2 ## 1.1.2 - 2017-07-17 - 通用 Mapper 3.4.1 - mybatis 3.4.4 - mybatis-spring-boot 1.3.0 - spring-boot 1.5.4.RELEASE ## 1.1.1 - 2017-03-28 - 解决 1.1.0 版本不一致的问题 - 增加对多数据源的支持,感谢 邱占波的 [PR #2](https://github.com/abel533/mapper-boot-starter/pull/2) ## 1.1.0 - 2017-02-19 - mybatis 升级到 3.4.2 - mapper 升级到 3.4.0 - mybatis-spring 升级到 1.3.1 - mybatis-spring-boot 升级到 1.2.0 - spring-boot 升级到 1.4.4.RELEASE ## Example > https://github.com/abel533/MyBatis-Spring-Boot ## Special Configurations 一般情况下,你不需要做任何配置。 Normally, you don't need to do any configuration. 如果需要配置,可以使用如下方式进行配置: You can config PageHelper as the following: application.properties: ```properties mapper.propertyName=propertyValue ``` 示例: ```properties mapper.mappers[0]=tk.mybatis.sample.mapper.BaseMapper mapper.mappers[1]=tk.mybatis.mapper.common.Mapper ``` 默认情况下,没有 mappers 配置时,会自动注册 `tk.mybatis.mapper.common.Mapper` 因为通用 Mapper 是固定的属性,所以接收参数使用的对象,按照 Spring Boot 配置规则,大写字母都变了带横线的小写字母。针对如 IDENTITY(对应i-d-e-n-t-i-t-y)提供了全小写的 identity 配置,如果 IDE 能自动提示,看自动提示即可。 IDE 应该可以自动提示: ![自动提示属性](properties.png) ## MyBatis Mapper > https://github.com/abel533/Mapper ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml ================================================ 4.0.0 tk.mybatis mapper-spring-boot ${revision} mapper-spring-boot-autoconfigure mapper-spring-boot-autoconfigure org.springframework.boot spring-boot-autoconfigure org.springframework.boot spring-boot-starter-jdbc true org.mybatis.scripting mybatis-freemarker true org.mybatis.scripting mybatis-velocity true org.mybatis.scripting mybatis-thymeleaf true tk.mybatis mapper-core true tk.mybatis mapper-spring true org.mybatis mybatis true org.mybatis mybatis-spring true org.slf4j slf4j-api true org.springframework.boot spring-boot-configuration-processor true jakarta.persistence jakarta.persistence-api true ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/ConfigurationCustomizer.java ================================================ /** * Copyright 2015-2017 the original author or authors. *

* 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 *

* http://www.apache.org/licenses/LICENSE-2.0 *

* 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 tk.mybatis.mapper.autoconfigure; import org.apache.ibatis.session.Configuration; /** * Callback interface that can be customized a {@link Configuration} object generated on auto-configuration. * * @author Kazuki Shimizu * @since 1.2.1 */ public interface ConfigurationCustomizer { /** * Customize the given a {@link Configuration} object. * * @param configuration the configuration object to customize */ void customize(Configuration configuration); } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java ================================================ /* * Copyright 2015-2022 the original author or authors. * * 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 * * https://www.apache.org/licenses/LICENSE-2.0 * * 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 tk.mybatis.mapper.autoconfigure; import java.beans.PropertyDescriptor; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.sql.DataSource; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.mapping.DatabaseIdProvider; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.TypeHandler; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.env.Environment; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import tk.mybatis.spring.annotation.BaseProperties; import tk.mybatis.spring.mapper.MapperFactoryBean; import tk.mybatis.spring.mapper.MapperScannerConfigurer; import tk.mybatis.spring.mapper.SpringBootBindUtil; /** * {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a {@link SqlSessionFactory} and a * {@link SqlSessionTemplate}. If {@link tk.mybatis.spring.annotation.MapperScan} is used, or a configuration file is * specified as a property, those will be considered, otherwise this auto-configuration will attempt to register mappers * based on the interface definitions in or under the root auto-configuration package. * * @author Eddú Meléndez * @author Josh Long * @author Kazuki Shimizu * @author Eduardo Macarrón */ @org.springframework.context.annotation.Configuration(proxyBeanMethods = false) @ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class}) @ConditionalOnSingleCandidate(DataSource.class) @EnableConfigurationProperties(MybatisProperties.class) @AutoConfigureBefore(name = "org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration") @AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class}) public class MapperAutoConfiguration implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(MapperAutoConfiguration.class); private final MybatisProperties properties; private final Interceptor[] interceptors; private final TypeHandler[] typeHandlers; private final LanguageDriver[] languageDrivers; private final ResourceLoader resourceLoader; private final DatabaseIdProvider databaseIdProvider; private final List configurationCustomizers; private final List sqlSessionFactoryBeanCustomizers; public MapperAutoConfiguration(MybatisProperties properties, ObjectProvider interceptorsProvider, ObjectProvider typeHandlersProvider, ObjectProvider languageDriversProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, ObjectProvider> configurationCustomizersProvider, ObjectProvider> sqlSessionFactoryBeanCustomizers) { this.properties = properties; this.interceptors = interceptorsProvider.getIfAvailable(); this.typeHandlers = typeHandlersProvider.getIfAvailable(); this.languageDrivers = languageDriversProvider.getIfAvailable(); this.resourceLoader = resourceLoader; this.databaseIdProvider = databaseIdProvider.getIfAvailable(); this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(); this.sqlSessionFactoryBeanCustomizers = sqlSessionFactoryBeanCustomizers.getIfAvailable(); } @Override public void afterPropertiesSet() { checkConfigFileExists(); } private void checkConfigFileExists() { if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) { Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation()); Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)"); } } @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); if (properties.getConfiguration() == null || properties.getConfiguration().getVfsImpl() == null) { factory.setVfs(SpringBootVFS.class); } if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } applyConfiguration(factory); if (this.properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(this.properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (this.properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.typeHandlers)) { factory.setTypeHandlers(this.typeHandlers); } Resource[] mapperLocations = this.properties.resolveMapperLocations(); if (!ObjectUtils.isEmpty(mapperLocations)) { factory.setMapperLocations(mapperLocations); } Set factoryPropertyNames = Stream .of(new BeanWrapperImpl(SqlSessionFactoryBean.class).getPropertyDescriptors()).map(PropertyDescriptor::getName) .collect(Collectors.toSet()); Class defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver(); if (factoryPropertyNames.contains("scriptingLanguageDrivers") && !ObjectUtils.isEmpty(this.languageDrivers)) { // Need to mybatis-spring 2.0.2+ factory.setScriptingLanguageDrivers(this.languageDrivers); if (defaultLanguageDriver == null && this.languageDrivers.length == 1) { defaultLanguageDriver = this.languageDrivers[0].getClass(); } } if (factoryPropertyNames.contains("defaultScriptingLanguageDriver")) { // Need to mybatis-spring 2.0.2+ factory.setDefaultScriptingLanguageDriver(defaultLanguageDriver); } applySqlSessionFactoryBeanCustomizers(factory); return factory.getObject(); } private void applyConfiguration(SqlSessionFactoryBean factory) { MybatisProperties.CoreConfiguration coreConfiguration = this.properties.getConfiguration(); Configuration configuration = null; if (coreConfiguration != null || !StringUtils.hasText(this.properties.getConfigLocation())) { configuration = new Configuration(); } if (configuration != null && coreConfiguration != null) { coreConfiguration.applyTo(configuration); } if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) { for (ConfigurationCustomizer customizer : this.configurationCustomizers) { customizer.customize(configuration); } } factory.setConfiguration(configuration); } private void applySqlSessionFactoryBeanCustomizers(SqlSessionFactoryBean factory) { if (!CollectionUtils.isEmpty(this.sqlSessionFactoryBeanCustomizers)) { for (SqlSessionFactoryBeanCustomizer customizer : this.sqlSessionFactoryBeanCustomizers) { customizer.customize(factory); } } } @Bean @ConditionalOnMissingBean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { ExecutorType executorType = this.properties.getExecutorType(); if (executorType != null) { return new SqlSessionTemplate(sqlSessionFactory, executorType); } else { return new SqlSessionTemplate(sqlSessionFactory); } } /** * This will just scan the same base package as Spring Boot does. If you want more power, you can explicitly use * {@link tk.mybatis.spring.annotation.MapperScan} but this will get typed mappers working correctly, out-of-the-box, * similar to using Spring Data JPA repositories. */ public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ResourceLoaderAware, EnvironmentAware, ImportBeanDefinitionRegistrar { private BeanFactory beanFactory; private ResourceLoader resourceLoader; private Environment environment; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { if (!AutoConfigurationPackages.has(this.beanFactory)) { logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled."); return; } BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); BaseProperties properties = SpringBootBindUtil.bind(environment, BaseProperties.class, BaseProperties.MYBATIS_PREFIX); if (properties != null && properties.getBasePackages() != null && properties.getBasePackages().length > 0) { List basePackages = Arrays.asList(properties.getBasePackages()); if (logger.isDebugEnabled()) { basePackages.forEach(pkg -> logger.debug("Using mybatis.basePackages configuration package '{}'", pkg)); } builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); } else { //设置了包名的情况下,不需要指定该注解 logger.debug("Searching for mappers annotated with @Mapper"); builder.addPropertyValue("annotationClass", Mapper.class); List packages = AutoConfigurationPackages.get(this.beanFactory); if (logger.isDebugEnabled()) { packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg)); } builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); } builder.addPropertyValue("processPropertyPlaceHolders", true); builder.addPropertyValue("mapperProperties", this.environment); BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class); Set propertyNames = Stream.of(beanWrapper.getPropertyDescriptors()).map(PropertyDescriptor::getName) .collect(Collectors.toSet()); if (propertyNames.contains("lazyInitialization")) { // Need to mybatis-spring 2.0.2+ builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}"); } if (propertyNames.contains("defaultScope")) { // Need to mybatis-spring 2.0.6+ builder.addPropertyValue("defaultScope", "${mybatis.mapper-default-scope:}"); } // for spring-native boolean injectSqlSession = environment.getProperty("mybatis.inject-sql-session-on-mapper-scan", Boolean.class, Boolean.TRUE); if (injectSqlSession && this.beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory; Optional sqlSessionTemplateBeanName = Optional .ofNullable(getBeanNameForType(SqlSessionTemplate.class, listableBeanFactory)); Optional sqlSessionFactoryBeanName = Optional .ofNullable(getBeanNameForType(SqlSessionFactory.class, listableBeanFactory)); if (sqlSessionTemplateBeanName.isPresent() || !sqlSessionFactoryBeanName.isPresent()) { builder.addPropertyValue("sqlSessionTemplateBeanName", sqlSessionTemplateBeanName.orElse("sqlSessionTemplate")); } else { builder.addPropertyValue("sqlSessionFactoryBeanName", sqlSessionFactoryBeanName.get()); } } builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition()); } @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Override public void setEnvironment(Environment environment) { this.environment = environment; } private String getBeanNameForType(Class type, ListableBeanFactory factory) { String[] beanNames = factory.getBeanNamesForType(type); return beanNames.length > 0 ? beanNames[0] : null; } } /** * If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan * mappers based on the same component-scanning path as Spring Boot itself. */ @org.springframework.context.annotation.Configuration(proxyBeanMethods = false) @Import(AutoConfiguredMapperScannerRegistrar.class) @ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class}) public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean { @Override public void afterPropertiesSet() { logger.debug( "Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer."); } } /** * Support Devtools Restart. */ @org.springframework.context.annotation.Configuration @ConditionalOnProperty(prefix = "spring.devtools.restart", name = "enabled", matchIfMissing = true) static class RestartConfiguration { @Bean public MapperCacheDisabler mapperCacheDisabler() { return new MapperCacheDisabler(); } } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperCacheDisabler.java ================================================ package tk.mybatis.mapper.autoconfigure; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Map; /** * 初始化完成后,清空类信息的缓存 * * @author liuzh */ public class MapperCacheDisabler implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(MapperCacheDisabler.class); @Override public void afterPropertiesSet() { disableCaching(); } private void disableCaching() { try { //因为jar包的类都是 AppClassLoader 加载的,所以此处获取的就是 AppClassLoader ClassLoader appClassLoader = getClass().getClassLoader(); removeStaticCache(ClassUtils.forName("tk.mybatis.mapper.util.MsUtil", appClassLoader), "CLASS_CACHE"); removeStaticCache(ClassUtils.forName("tk.mybatis.mapper.genid.GenIdUtil", appClassLoader)); removeStaticCache(ClassUtils.forName("tk.mybatis.mapper.version.VersionUtil", appClassLoader)); removeEntityHelperCache(ClassUtils.forName("tk.mybatis.mapper.mapperhelper.EntityHelper", appClassLoader)); } catch (Exception ex) { } } private void removeStaticCache(Class utilClass) { removeStaticCache(utilClass, "CACHE"); } private void removeStaticCache(Class utilClass, String fieldName) { try { Field cacheField = ReflectionUtils.findField(utilClass, fieldName); if (cacheField != null) { ReflectionUtils.makeAccessible(cacheField); Object cache = ReflectionUtils.getField(cacheField, null); if (cache instanceof Map) { ((Map) cache).clear(); } else if (cache instanceof Cache) { ((Cache) cache).clear(); } else { throw new UnsupportedOperationException("cache field must be a java.util.Map " + "or org.apache.ibatis.cache.Cache instance"); } logger.info("Clear " + utilClass.getName() + " " + fieldName + " cache."); } } catch (Exception ex) { logger.warn("Failed to disable " + utilClass.getName() + " " + fieldName + " cache. ClassCastExceptions may occur", ex); } } private void removeEntityHelperCache(Class entityHelper) { try { Field cacheField = ReflectionUtils.findField(entityHelper, "entityTableMap"); if (cacheField != null) { ReflectionUtils.makeAccessible(cacheField); Map cache = (Map) ReflectionUtils.getField(cacheField, null); //如果使用了 Devtools,这里获取的就是当前的 RestartClassLoader ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); for (Object key : new ArrayList(cache.keySet())) { Class entityClass = (Class) key; //清理老的ClassLoader缓存的数据,避免测试环境溢出 if (!(entityClass.getClassLoader().equals(classLoader) || entityClass.getClassLoader().equals(classLoader.getParent()))) { cache.remove(entityClass); } } logger.info("Clear EntityHelper entityTableMap cache."); } } catch (Exception ex) { logger.warn("Failed to disable Mapper MsUtil cache. ClassCastExceptions may occur", ex); } } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperProperties.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.autoconfigure; import org.springframework.boot.context.properties.ConfigurationProperties; import tk.mybatis.mapper.entity.Config; /** * 这个类存在的主要目的是方便 IDE 自动提示 mapper. 开头的配置 * * @author liuzh * @since 2017/1/2. */ @ConfigurationProperties(prefix = MapperProperties.PREFIX) public class MapperProperties extends Config { } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisDependsOnDatabaseInitializationDetector.java ================================================ package tk.mybatis.mapper.autoconfigure; import java.util.Collections; import java.util.Set; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDependsOnDatabaseInitializationDetector; import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector; /** * {@link DependsOnDatabaseInitializationDetector} for Mybatis. * * @author Eddú Meléndez * @since 2.3.0 */ class MybatisDependsOnDatabaseInitializationDetector extends AbstractBeansOfTypeDependsOnDatabaseInitializationDetector { @Override protected Set> getDependsOnDatabaseInitializationBeanTypes() { return Collections.singleton(SqlSessionTemplate.class); } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisLanguageDriverAutoConfiguration.java ================================================ package tk.mybatis.mapper.autoconfigure; import org.apache.ibatis.scripting.LanguageDriver; import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver; import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig; import org.mybatis.scripting.velocity.VelocityLanguageDriver; import org.mybatis.scripting.velocity.VelocityLanguageDriverConfig; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * {@link EnableAutoConfiguration Auto-Configuration} for MyBatis's scripting language drivers. * * @author Kazuki Shimizu * @since 2.1.0 */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(LanguageDriver.class) public class MybatisLanguageDriverAutoConfiguration { private static final String CONFIGURATION_PROPERTY_PREFIX = "mybatis.scripting-language-driver"; /** * Configuration class for mybatis-freemarker 1.1.x or under. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(FreeMarkerLanguageDriver.class) @ConditionalOnMissingClass("org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig") public static class LegacyFreeMarkerConfiguration { @Bean @ConditionalOnMissingBean FreeMarkerLanguageDriver freeMarkerLanguageDriver() { return new FreeMarkerLanguageDriver(); } } /** * Configuration class for mybatis-freemarker 1.2.x or above. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({FreeMarkerLanguageDriver.class, FreeMarkerLanguageDriverConfig.class}) public static class FreeMarkerConfiguration { @Bean @ConditionalOnMissingBean FreeMarkerLanguageDriver freeMarkerLanguageDriver(FreeMarkerLanguageDriverConfig config) { return new FreeMarkerLanguageDriver(config); } @Bean @ConditionalOnMissingBean @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".freemarker") public FreeMarkerLanguageDriverConfig freeMarkerLanguageDriverConfig() { return FreeMarkerLanguageDriverConfig.newInstance(); } } /** * Configuration class for mybatis-velocity 2.0 or under. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(org.mybatis.scripting.velocity.Driver.class) @ConditionalOnMissingClass("org.mybatis.scripting.velocity.VelocityLanguageDriverConfig") @SuppressWarnings("deprecation") public static class LegacyVelocityConfiguration { @Bean @ConditionalOnMissingBean org.mybatis.scripting.velocity.Driver velocityLanguageDriver() { return new org.mybatis.scripting.velocity.Driver(); } } /** * Configuration class for mybatis-velocity 2.1.x or above. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({VelocityLanguageDriver.class, VelocityLanguageDriverConfig.class}) public static class VelocityConfiguration { @Bean @ConditionalOnMissingBean VelocityLanguageDriver velocityLanguageDriver(VelocityLanguageDriverConfig config) { return new VelocityLanguageDriver(config); } @Bean @ConditionalOnMissingBean @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".velocity") public VelocityLanguageDriverConfig velocityLanguageDriverConfig() { return VelocityLanguageDriverConfig.newInstance(); } } @Configuration(proxyBeanMethods = false) @ConditionalOnClass(ThymeleafLanguageDriver.class) public static class ThymeleafConfiguration { @Bean @ConditionalOnMissingBean ThymeleafLanguageDriver thymeleafLanguageDriver(ThymeleafLanguageDriverConfig config) { return new ThymeleafLanguageDriver(config); } @Bean @ConditionalOnMissingBean @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf") public ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig() { return ThymeleafLanguageDriverConfig.newInstance(); } // This class provides to avoid the https://github.com/spring-projects/spring-boot/issues/21626 as workaround. @SuppressWarnings("unused") private static class MetadataThymeleafLanguageDriverConfig extends ThymeleafLanguageDriverConfig { @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf.dialect") @Override public DialectConfig getDialect() { return super.getDialect(); } @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf.template-file") @Override public TemplateFileConfig getTemplateFile() { return super.getTemplateFile(); } } } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisProperties.java ================================================ /** * Copyright 2015-2017 the original author or authors. *

* 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 *

* http://www.apache.org/licenses/LICENSE-2.0 *

* 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 tk.mybatis.mapper.autoconfigure; import org.apache.ibatis.io.VFS; import org.apache.ibatis.logging.Log; import org.apache.ibatis.mapping.ResultSetType; import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.session.AutoMappingBehavior; import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.LocalCacheScope; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import tk.mybatis.spring.annotation.BaseProperties; import java.io.IOException; import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.stream.Stream; /** * Configuration properties for MyBatis. * * @author Eddú Meléndez * @author Kazuki Shimizu */ @ConfigurationProperties(prefix = BaseProperties.MYBATIS_PREFIX) public class MybatisProperties extends BaseProperties { private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); /** * Location of MyBatis xml config file. */ private String configLocation; /** * Locations of MyBatis mapper files. */ private String[] mapperLocations; /** * Packages to search type aliases. (Package delimiters are ",; \t\n") */ private String typeAliasesPackage; /** * The super class for filtering type alias. If this not specifies, the MyBatis deal as type alias all classes that * searched from typeAliasesPackage. */ private Class typeAliasesSuperType; /** * Packages to search for type handlers. (Package delimiters are ",; \t\n") */ private String typeHandlersPackage; /** * Indicates whether perform presence check of the MyBatis xml config file. */ private boolean checkConfigLocation = false; /** * Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}. */ private ExecutorType executorType; /** * The default scripting language driver class. (Available when use together with mybatis-spring 2.0.2+) */ private Class defaultScriptingLanguageDriver; /** * Externalized properties for MyBatis configuration. */ private Properties configurationProperties; /** * A Configuration object for customize default settings. If {@link #configLocation} is specified, this property is * not used. */ private CoreConfiguration configuration; /** * @since 1.1.0 */ public String getConfigLocation() { return this.configLocation; } /** * @since 1.1.0 */ public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } public String[] getMapperLocations() { return this.mapperLocations; } public void setMapperLocations(String[] mapperLocations) { this.mapperLocations = mapperLocations; } public String getTypeHandlersPackage() { return this.typeHandlersPackage; } public void setTypeHandlersPackage(String typeHandlersPackage) { this.typeHandlersPackage = typeHandlersPackage; } public String getTypeAliasesPackage() { return this.typeAliasesPackage; } public void setTypeAliasesPackage(String typeAliasesPackage) { this.typeAliasesPackage = typeAliasesPackage; } /** * @since 1.3.3 */ public Class getTypeAliasesSuperType() { return typeAliasesSuperType; } /** * @since 1.3.3 */ public void setTypeAliasesSuperType(Class typeAliasesSuperType) { this.typeAliasesSuperType = typeAliasesSuperType; } public boolean isCheckConfigLocation() { return this.checkConfigLocation; } public void setCheckConfigLocation(boolean checkConfigLocation) { this.checkConfigLocation = checkConfigLocation; } public ExecutorType getExecutorType() { return this.executorType; } public void setExecutorType(ExecutorType executorType) { this.executorType = executorType; } /** * @since 2.1.0 */ public Class getDefaultScriptingLanguageDriver() { return defaultScriptingLanguageDriver; } /** * @since 2.1.0 */ public void setDefaultScriptingLanguageDriver(Class defaultScriptingLanguageDriver) { this.defaultScriptingLanguageDriver = defaultScriptingLanguageDriver; } /** * @since 1.2.0 */ public Properties getConfigurationProperties() { return configurationProperties; } /** * @since 1.2.0 */ public void setConfigurationProperties(Properties configurationProperties) { this.configurationProperties = configurationProperties; } public CoreConfiguration getConfiguration() { return configuration; } public void setConfiguration(CoreConfiguration configuration) { this.configuration = configuration; } public Resource[] resolveMapperLocations() { return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0])) .flatMap(location -> Stream.of(getResources(location))).toArray(Resource[]::new); } private Resource[] getResources(String location) { try { return resourceResolver.getResources(location); } catch (IOException e) { return new Resource[0]; } } /** * The configuration properties for mybatis core module. * * @since 3.0.0 */ public static class CoreConfiguration { /** * Specifies the TypeHandler used by default for Enum. */ Class defaultEnumTypeHandler; /** * Allows using RowBounds on nested statements. If allow, set the false. Default is false. */ private Boolean safeRowBoundsEnabled; /** * Allows using ResultHandler on nested statements. If allow, set the false. Default is true. */ private Boolean safeResultHandlerEnabled; /** * Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names * aColumn. Default is false. */ private Boolean mapUnderscoreToCamelCase; /** * When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded * on demand (see also lazyLoadTriggerMethods). Default is false. */ private Boolean aggressiveLazyLoading; /** * Allows or disallows multiple ResultSets to be returned from a single statement (compatible driver required). * Default is true. */ private Boolean multipleResultSetsEnabled; /** * Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be * used if set to true, as some drivers deny compatibility but still work (e.g. Derby). Default is false. */ private Boolean useGeneratedKeys; /** * Uses the column label instead of the column name. Different drivers behave differently in this respect. Refer to * the driver documentation, or test out both modes to determine how your driver behaves. Default is true. */ private Boolean useColumnLabel; /** * Globally enables or disables any caches configured in any mapper under this configuration. Default is true. */ private Boolean cacheEnabled; /** * Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you * rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to * null. Default is false. */ private Boolean callSettersOnNulls; /** * Allow referencing statement parameters by their actual names declared in the method signature. To use this * feature, your project must be compiled in Java 8 with -parameters option. Default is true. */ private Boolean useActualParamName; /** * MyBatis, by default, returns null when all the columns of a returned row are NULL. When this setting is enabled, * MyBatis returns an empty instance instead. Note that it is also applied to nested results (i.e. collectioin and * association). Default is false. */ private Boolean returnInstanceForEmptyRow; /** * Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. Default is * false. */ private Boolean shrinkWhitespacesInSql; /** * Specifies the default value of 'nullable' attribute on 'foreach' tag. Default is false. */ private Boolean nullableOnForEach; /** * When applying constructor auto-mapping, argument name is used to search the column to map instead of relying on * the column order. Default is false. */ private Boolean argNameBasedConstructorAutoMapping; /** * Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. This value can be * superseded for a specific relation by using the fetchType attribute on it. Default is False. */ private Boolean lazyLoadingEnabled; /** * Sets the number of seconds the driver will wait for a response from the database. */ private Integer defaultStatementTimeout; /** * Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a * query setting. */ private Integer defaultFetchSize; /** * MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default * (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be * used just for statement execution, no data will be shared between two different calls to the same SqlSession. * Default is SESSION. */ private LocalCacheScope localCacheScope; /** * Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers * require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. Default * is OTHER. */ private JdbcType jdbcTypeForNull; /** * Specifies a scroll strategy when omit it per statement settings. */ private ResultSetType defaultResultSetType; /** * Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements. * BATCH executor reuses statements and batches updates. Default is SIMPLE. */ private ExecutorType defaultExecutorType; /** * Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping. * PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result * mappings of any complexity (containing nested or otherwise). Default is PARTIAL. */ private AutoMappingBehavior autoMappingBehavior; /** * Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target. * Default is NONE. */ private AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior; /** * Specifies the prefix string that MyBatis will add to the logger names. */ private String logPrefix; /** * Specifies which Object's methods trigger a lazy load. Default is [equals,clone,hashCode,toString]. */ private Set lazyLoadTriggerMethods; /** * Specifies which logging implementation MyBatis should use. If this setting is not present logging implementation * will be autodiscovered. */ private Class logImpl; /** * Specifies VFS implementations. */ private Class vfsImpl; /** * Specifies an sql provider class that holds provider method. This class apply to the type(or value) attribute on * sql provider annotation(e.g. @SelectProvider), when these attribute was omitted. */ private Class defaultSqlProviderType; /** * Specifies the class that provides an instance of Configuration. The returned Configuration instance is used to * load lazy properties of deserialized objects. This class must have a method with a signature static Configuration * getConfiguration(). */ private Class configurationFactory; /** * Specify any configuration variables. */ private Properties variables; /** * Specifies the database identify value for switching query to use. */ private String databaseId; public Boolean getSafeRowBoundsEnabled() { return safeRowBoundsEnabled; } public void setSafeRowBoundsEnabled(Boolean safeRowBoundsEnabled) { this.safeRowBoundsEnabled = safeRowBoundsEnabled; } public Boolean getSafeResultHandlerEnabled() { return safeResultHandlerEnabled; } public void setSafeResultHandlerEnabled(Boolean safeResultHandlerEnabled) { this.safeResultHandlerEnabled = safeResultHandlerEnabled; } public Boolean getMapUnderscoreToCamelCase() { return mapUnderscoreToCamelCase; } public void setMapUnderscoreToCamelCase(Boolean mapUnderscoreToCamelCase) { this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase; } public Boolean getAggressiveLazyLoading() { return aggressiveLazyLoading; } public void setAggressiveLazyLoading(Boolean aggressiveLazyLoading) { this.aggressiveLazyLoading = aggressiveLazyLoading; } public Boolean getMultipleResultSetsEnabled() { return multipleResultSetsEnabled; } public void setMultipleResultSetsEnabled(Boolean multipleResultSetsEnabled) { this.multipleResultSetsEnabled = multipleResultSetsEnabled; } public Boolean getUseGeneratedKeys() { return useGeneratedKeys; } public void setUseGeneratedKeys(Boolean useGeneratedKeys) { this.useGeneratedKeys = useGeneratedKeys; } public Boolean getUseColumnLabel() { return useColumnLabel; } public void setUseColumnLabel(Boolean useColumnLabel) { this.useColumnLabel = useColumnLabel; } public Boolean getCacheEnabled() { return cacheEnabled; } public void setCacheEnabled(Boolean cacheEnabled) { this.cacheEnabled = cacheEnabled; } public Boolean getCallSettersOnNulls() { return callSettersOnNulls; } public void setCallSettersOnNulls(Boolean callSettersOnNulls) { this.callSettersOnNulls = callSettersOnNulls; } public Boolean getUseActualParamName() { return useActualParamName; } public void setUseActualParamName(Boolean useActualParamName) { this.useActualParamName = useActualParamName; } public Boolean getReturnInstanceForEmptyRow() { return returnInstanceForEmptyRow; } public void setReturnInstanceForEmptyRow(Boolean returnInstanceForEmptyRow) { this.returnInstanceForEmptyRow = returnInstanceForEmptyRow; } public Boolean getShrinkWhitespacesInSql() { return shrinkWhitespacesInSql; } public void setShrinkWhitespacesInSql(Boolean shrinkWhitespacesInSql) { this.shrinkWhitespacesInSql = shrinkWhitespacesInSql; } public Boolean getNullableOnForEach() { return nullableOnForEach; } public void setNullableOnForEach(Boolean nullableOnForEach) { this.nullableOnForEach = nullableOnForEach; } public Boolean getArgNameBasedConstructorAutoMapping() { return argNameBasedConstructorAutoMapping; } public void setArgNameBasedConstructorAutoMapping(Boolean argNameBasedConstructorAutoMapping) { this.argNameBasedConstructorAutoMapping = argNameBasedConstructorAutoMapping; } public String getLogPrefix() { return logPrefix; } public void setLogPrefix(String logPrefix) { this.logPrefix = logPrefix; } public Class getLogImpl() { return logImpl; } public void setLogImpl(Class logImpl) { this.logImpl = logImpl; } public Class getVfsImpl() { return vfsImpl; } public void setVfsImpl(Class vfsImpl) { this.vfsImpl = vfsImpl; } public Class getDefaultSqlProviderType() { return defaultSqlProviderType; } public void setDefaultSqlProviderType(Class defaultSqlProviderType) { this.defaultSqlProviderType = defaultSqlProviderType; } public LocalCacheScope getLocalCacheScope() { return localCacheScope; } public void setLocalCacheScope(LocalCacheScope localCacheScope) { this.localCacheScope = localCacheScope; } public JdbcType getJdbcTypeForNull() { return jdbcTypeForNull; } public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) { this.jdbcTypeForNull = jdbcTypeForNull; } public Set getLazyLoadTriggerMethods() { return lazyLoadTriggerMethods; } public void setLazyLoadTriggerMethods(Set lazyLoadTriggerMethods) { this.lazyLoadTriggerMethods = lazyLoadTriggerMethods; } public Integer getDefaultStatementTimeout() { return defaultStatementTimeout; } public void setDefaultStatementTimeout(Integer defaultStatementTimeout) { this.defaultStatementTimeout = defaultStatementTimeout; } public Integer getDefaultFetchSize() { return defaultFetchSize; } public void setDefaultFetchSize(Integer defaultFetchSize) { this.defaultFetchSize = defaultFetchSize; } public ResultSetType getDefaultResultSetType() { return defaultResultSetType; } public void setDefaultResultSetType(ResultSetType defaultResultSetType) { this.defaultResultSetType = defaultResultSetType; } public ExecutorType getDefaultExecutorType() { return defaultExecutorType; } public void setDefaultExecutorType(ExecutorType defaultExecutorType) { this.defaultExecutorType = defaultExecutorType; } public AutoMappingBehavior getAutoMappingBehavior() { return autoMappingBehavior; } public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) { this.autoMappingBehavior = autoMappingBehavior; } public AutoMappingUnknownColumnBehavior getAutoMappingUnknownColumnBehavior() { return autoMappingUnknownColumnBehavior; } public void setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior) { this.autoMappingUnknownColumnBehavior = autoMappingUnknownColumnBehavior; } public Properties getVariables() { return variables; } public void setVariables(Properties variables) { this.variables = variables; } public Boolean getLazyLoadingEnabled() { return lazyLoadingEnabled; } public void setLazyLoadingEnabled(Boolean lazyLoadingEnabled) { this.lazyLoadingEnabled = lazyLoadingEnabled; } public Class getConfigurationFactory() { return configurationFactory; } public void setConfigurationFactory(Class configurationFactory) { this.configurationFactory = configurationFactory; } public Class getDefaultEnumTypeHandler() { return defaultEnumTypeHandler; } public void setDefaultEnumTypeHandler(Class defaultEnumTypeHandler) { this.defaultEnumTypeHandler = defaultEnumTypeHandler; } public String getDatabaseId() { return databaseId; } public void setDatabaseId(String databaseId) { this.databaseId = databaseId; } public void applyTo(Configuration target) { PropertyMapper mapper = PropertyMapper.get(); mapper.from(getSafeRowBoundsEnabled()).to(target::setSafeRowBoundsEnabled); mapper.from(getSafeResultHandlerEnabled()).to(target::setSafeResultHandlerEnabled); mapper.from(getMapUnderscoreToCamelCase()).to(target::setMapUnderscoreToCamelCase); mapper.from(getAggressiveLazyLoading()).to(target::setAggressiveLazyLoading); mapper.from(getMultipleResultSetsEnabled()).to(target::setMultipleResultSetsEnabled); mapper.from(getUseGeneratedKeys()).to(target::setUseGeneratedKeys); mapper.from(getUseColumnLabel()).to(target::setUseColumnLabel); mapper.from(getCacheEnabled()).to(target::setCacheEnabled); mapper.from(getCallSettersOnNulls()).to(target::setCallSettersOnNulls); mapper.from(getUseActualParamName()).to(target::setUseActualParamName); mapper.from(getReturnInstanceForEmptyRow()).to(target::setReturnInstanceForEmptyRow); mapper.from(getShrinkWhitespacesInSql()).to(target::setShrinkWhitespacesInSql); mapper.from(getNullableOnForEach()).to(target::setNullableOnForEach); mapper.from(getArgNameBasedConstructorAutoMapping()).to(target::setArgNameBasedConstructorAutoMapping); mapper.from(getLazyLoadingEnabled()).to(target::setLazyLoadingEnabled); mapper.from(getLogPrefix()).to(target::setLogPrefix); mapper.from(getLazyLoadTriggerMethods()).to(target::setLazyLoadTriggerMethods); mapper.from(getDefaultStatementTimeout()).to(target::setDefaultStatementTimeout); mapper.from(getDefaultFetchSize()).to(target::setDefaultFetchSize); mapper.from(getLocalCacheScope()).to(target::setLocalCacheScope); mapper.from(getJdbcTypeForNull()).to(target::setJdbcTypeForNull); mapper.from(getDefaultResultSetType()).to(target::setDefaultResultSetType); mapper.from(getDefaultExecutorType()).to(target::setDefaultExecutorType); mapper.from(getAutoMappingBehavior()).to(target::setAutoMappingBehavior); mapper.from(getAutoMappingUnknownColumnBehavior()).to(target::setAutoMappingUnknownColumnBehavior); mapper.from(getVariables()).to(target::setVariables); mapper.from(getLogImpl()).to(target::setLogImpl); mapper.from(getVfsImpl()).to(target::setVfsImpl); mapper.from(getDefaultSqlProviderType()).to(target::setDefaultSqlProviderType); mapper.from(getConfigurationFactory()).to(target::setConfigurationFactory); mapper.from(getDefaultEnumTypeHandler()).to(target::setDefaultEnumTypeHandler); mapper.from(getDatabaseId()).to(target::setDatabaseId); } } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SpringBootVFS.java ================================================ /** * Copyright 2015-2017 the original author or authors. *

* 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 *

* http://www.apache.org/licenses/LICENSE-2.0 *

* 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 tk.mybatis.mapper.autoconfigure; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.Charset; import java.text.Normalizer; import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.ibatis.io.VFS; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.util.ClassUtils; /** * @author Hans Westerbeek * @author Eddú Meléndez * @author Kazuki Shimizu */ public class SpringBootVFS extends VFS { private static Charset urlDecodingCharset; private static Supplier classLoaderSupplier; private final ResourcePatternResolver resourceResolver; static { setUrlDecodingCharset(Charset.defaultCharset()); setClassLoaderSupplier(ClassUtils::getDefaultClassLoader); } public SpringBootVFS() { this.resourceResolver = new PathMatchingResourcePatternResolver(classLoaderSupplier.get()); } @Override public boolean isValid() { return true; } /** * Set the charset for decoding an encoded URL string. *

* Default is system default charset. *

* * @param charset the charset for decoding an encoded URL string * @since 2.3.0 */ public static void setUrlDecodingCharset(Charset charset) { urlDecodingCharset = charset; } /** * Set the supplier for providing {@link ClassLoader} to used. *

* Default is a returned instance from {@link ClassUtils#getDefaultClassLoader()}. *

* * @param supplier the supplier for providing {@link ClassLoader} to used * @since 3.0.2 */ public static void setClassLoaderSupplier(Supplier supplier) { classLoaderSupplier = supplier; } private static String preserveSubpackageName(final String baseUrlString, final Resource resource, final String rootPath) { try { return rootPath + (rootPath.endsWith("/") ? "" : "/") + Normalizer .normalize(URLDecoder.decode(resource.getURL().toString(), urlDecodingCharset), Normalizer.Form.NFC) .substring(baseUrlString.length()); } catch (IOException e) { throw new UncheckedIOException(e); } } @Override protected List list(URL url, String path) throws IOException { String urlString = URLDecoder.decode(url.toString(), urlDecodingCharset); String baseUrlString = urlString.endsWith("/") ? urlString : urlString.concat("/"); Resource[] resources = resourceResolver.getResources(baseUrlString + "**/*.class"); return Stream.of(resources).map(resource -> preserveSubpackageName(baseUrlString, resource, path)) .collect(Collectors.toList()); } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SqlSessionFactoryBeanCustomizer.java ================================================ package tk.mybatis.mapper.autoconfigure; import org.mybatis.spring.SqlSessionFactoryBean; /** * Callback interface that can be customized a {@link SqlSessionFactoryBean} object generated on auto-configuration. * * @author Kazuki Shimizu * @since 2.2.2 */ @FunctionalInterface public interface SqlSessionFactoryBeanCustomizer { /** * Customize the given a {@link SqlSessionFactoryBean} object. * * @param factoryBean the factory bean object to customize */ void customize(SqlSessionFactoryBean factoryBean); } ================================================ FILE: spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports ================================================ tk.mybatis.mapper.autoconfigure.MybatisLanguageDriverAutoConfiguration tk.mybatis.mapper.autoconfigure.MapperAutoConfiguration ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/pom.xml ================================================ 4.0.0 tk.mybatis mapper-spring-boot-samples ${revision} mapper-spring-boot-sample-annotation jar mapper-spring-boot-sample-annotation org.slf4j slf4j-api runtime tk.mybatis mapper-spring-boot-starter com.h2database h2 runtime org.springframework.boot spring-boot-maven-plugin ${spring-boot.version} ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/SampleMapperApplication.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import tk.mybatis.sample.domain.Country; import tk.mybatis.sample.mapper.CountryMapper; import tk.mybatis.spring.annotation.MapperScan; import java.util.List; @MapperScan(basePackages = "tk.mybatis.sample.mapper") @SpringBootApplication public class SampleMapperApplication implements CommandLineRunner { @Autowired private CountryMapper countryMapper; public static void main(String[] args) { SpringApplication.run(SampleMapperApplication.class, args); } @Override public void run(String... args) throws Exception { List countries = countryMapper.selectAll(); for (Country country : countries) { System.out.println("Country Name: " + country.getCountryname()); } } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/domain/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample.domain; import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.annotation.ColumnType; import jakarta.persistence.Id; import java.io.Serializable; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ public class Country implements Serializable { private static final long serialVersionUID = 6569081236403751407L; @Id @ColumnType(jdbcType = JdbcType.BIGINT) private Long id; private String countryname; private String countrycode; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/mapper/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample.mapper; import org.apache.ibatis.annotations.Mapper; import tk.mybatis.sample.domain.Country; @Mapper public interface CountryMapper extends tk.mybatis.mapper.common.Mapper { } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties ================================================ # # The MIT License (MIT) # # Copyright (c) 2017 abel533@gmail.com # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # spring.sql.init.schema-locations=classpath:import.sql logging.level.root=WARN logging.level.tk.mybatis.sample.mapper=TRACE mapper.useSimpleType=false mapper.enable-method-annotation=true mapper.style=uppercase mybatis.configuration.logImpl=org.apache.ibatis.logging.slf4j.Slf4jImpl ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/import.sql ================================================ drop table country if exists; create table country ( id int primary key auto_increment, countryname varchar(32), countrycode varchar(2) ); insert into country (id, countryname, countrycode) values (1, 'Angola', 'AO'); insert into country (id, countryname, countrycode) values (2, 'Afghanistan', 'AF'); insert into country (id, countryname, countrycode) values (3, 'Albania', 'AL'); insert into country (id, countryname, countrycode) values (4, 'Algeria', 'DZ'); insert into country (id, countryname, countrycode) values (5, 'Andorra', 'AD'); insert into country (id, countryname, countrycode) values (6, 'Anguilla', 'AI'); insert into country (id, countryname, countrycode) values (7, 'Antigua and Barbuda', 'AG'); insert into country (id, countryname, countrycode) values (8, 'Argentina', 'AR'); insert into country (id, countryname, countrycode) values (9, 'Armenia', 'AM'); insert into country (id, countryname, countrycode) values (10, 'Australia', 'AU'); insert into country (id, countryname, countrycode) values (11, 'Austria', 'AT'); insert into country (id, countryname, countrycode) values (12, 'Azerbaijan', 'AZ'); insert into country (id, countryname, countrycode) values (13, 'Bahamas', 'BS'); insert into country (id, countryname, countrycode) values (14, 'Bahrain', 'BH'); insert into country (id, countryname, countrycode) values (15, 'Bangladesh', 'BD'); insert into country (id, countryname, countrycode) values (16, 'Barbados', 'BB'); insert into country (id, countryname, countrycode) values (17, 'Belarus', 'BY'); insert into country (id, countryname, countrycode) values (18, 'Belgium', 'BE'); insert into country (id, countryname, countrycode) values (19, 'Belize', 'BZ'); insert into country (id, countryname, countrycode) values (20, 'Benin', 'BJ'); insert into country (id, countryname, countrycode) values (21, 'Bermuda Is.', 'BM'); insert into country (id, countryname, countrycode) values (22, 'Bolivia', 'BO'); insert into country (id, countryname, countrycode) values (23, 'Botswana', 'BW'); insert into country (id, countryname, countrycode) values (24, 'Brazil', 'BR'); insert into country (id, countryname, countrycode) values (25, 'Brunei', 'BN'); insert into country (id, countryname, countrycode) values (26, 'Bulgaria', 'BG'); insert into country (id, countryname, countrycode) values (27, 'Burkina-faso', 'BF'); insert into country (id, countryname, countrycode) values (28, 'Burma', 'MM'); insert into country (id, countryname, countrycode) values (29, 'Burundi', 'BI'); insert into country (id, countryname, countrycode) values (30, 'Cameroon', 'CM'); insert into country (id, countryname, countrycode) values (31, 'Canada', 'CA'); insert into country (id, countryname, countrycode) values (32, 'Central African Republic', 'CF'); insert into country (id, countryname, countrycode) values (33, 'Chad', 'TD'); insert into country (id, countryname, countrycode) values (34, 'Chile', 'CL'); insert into country (id, countryname, countrycode) values (35, 'China', 'CN'); insert into country (id, countryname, countrycode) values (36, 'Colombia', 'CO'); insert into country (id, countryname, countrycode) values (37, 'Congo', 'CG'); insert into country (id, countryname, countrycode) values (38, 'Cook Is.', 'CK'); insert into country (id, countryname, countrycode) values (39, 'Costa Rica', 'CR'); insert into country (id, countryname, countrycode) values (40, 'Cuba', 'CU'); insert into country (id, countryname, countrycode) values (41, 'Cyprus', 'CY'); insert into country (id, countryname, countrycode) values (42, 'Czech Republic', 'CZ'); insert into country (id, countryname, countrycode) values (43, 'Denmark', 'DK'); insert into country (id, countryname, countrycode) values (44, 'Djibouti', 'DJ'); insert into country (id, countryname, countrycode) values (45, 'Dominica Rep.', 'DO'); insert into country (id, countryname, countrycode) values (46, 'Ecuador', 'EC'); insert into country (id, countryname, countrycode) values (47, 'Egypt', 'EG'); insert into country (id, countryname, countrycode) values (48, 'EI Salvador', 'SV'); insert into country (id, countryname, countrycode) values (49, 'Estonia', 'EE'); insert into country (id, countryname, countrycode) values (50, 'Ethiopia', 'ET'); insert into country (id, countryname, countrycode) values (51, 'Fiji', 'FJ'); insert into country (id, countryname, countrycode) values (52, 'Finland', 'FI'); insert into country (id, countryname, countrycode) values (53, 'France', 'FR'); insert into country (id, countryname, countrycode) values (54, 'French Guiana', 'GF'); insert into country (id, countryname, countrycode) values (55, 'Gabon', 'GA'); insert into country (id, countryname, countrycode) values (56, 'Gambia', 'GM'); insert into country (id, countryname, countrycode) values (57, 'Georgia', 'GE'); insert into country (id, countryname, countrycode) values (58, 'Germany', 'DE'); insert into country (id, countryname, countrycode) values (59, 'Ghana', 'GH'); insert into country (id, countryname, countrycode) values (60, 'Gibraltar', 'GI'); insert into country (id, countryname, countrycode) values (61, 'Greece', 'GR'); insert into country (id, countryname, countrycode) values (62, 'Grenada', 'GD'); insert into country (id, countryname, countrycode) values (63, 'Guam', 'GU'); insert into country (id, countryname, countrycode) values (64, 'Guatemala', 'GT'); insert into country (id, countryname, countrycode) values (65, 'Guinea', 'GN'); insert into country (id, countryname, countrycode) values (66, 'Guyana', 'GY'); insert into country (id, countryname, countrycode) values (67, 'Haiti', 'HT'); insert into country (id, countryname, countrycode) values (68, 'Honduras', 'HN'); insert into country (id, countryname, countrycode) values (69, 'Hongkong', 'HK'); insert into country (id, countryname, countrycode) values (70, 'Hungary', 'HU'); insert into country (id, countryname, countrycode) values (71, 'Iceland', 'IS'); insert into country (id, countryname, countrycode) values (72, 'India', 'IN'); insert into country (id, countryname, countrycode) values (73, 'Indonesia', 'ID'); insert into country (id, countryname, countrycode) values (74, 'Iran', 'IR'); insert into country (id, countryname, countrycode) values (75, 'Iraq', 'IQ'); insert into country (id, countryname, countrycode) values (76, 'Ireland', 'IE'); insert into country (id, countryname, countrycode) values (77, 'Israel', 'IL'); insert into country (id, countryname, countrycode) values (78, 'Italy', 'IT'); insert into country (id, countryname, countrycode) values (79, 'Jamaica', 'JM'); insert into country (id, countryname, countrycode) values (80, 'Japan', 'JP'); insert into country (id, countryname, countrycode) values (81, 'Jordan', 'JO'); insert into country (id, countryname, countrycode) values (82, 'Kampuchea (Cambodia )', 'KH'); insert into country (id, countryname, countrycode) values (83, 'Kazakstan', 'KZ'); insert into country (id, countryname, countrycode) values (84, 'Kenya', 'KE'); insert into country (id, countryname, countrycode) values (85, 'Korea', 'KR'); insert into country (id, countryname, countrycode) values (86, 'Kuwait', 'KW'); insert into country (id, countryname, countrycode) values (87, 'Kyrgyzstan', 'KG'); insert into country (id, countryname, countrycode) values (88, 'Laos', 'LA'); insert into country (id, countryname, countrycode) values (89, 'Latvia', 'LV'); insert into country (id, countryname, countrycode) values (90, 'Lebanon', 'LB'); insert into country (id, countryname, countrycode) values (91, 'Lesotho', 'LS'); insert into country (id, countryname, countrycode) values (92, 'Liberia', 'LR'); insert into country (id, countryname, countrycode) values (93, 'Libya', 'LY'); insert into country (id, countryname, countrycode) values (94, 'Liechtenstein', 'LI'); insert into country (id, countryname, countrycode) values (95, 'Lithuania', 'LT'); insert into country (id, countryname, countrycode) values (96, 'Luxembourg', 'LU'); insert into country (id, countryname, countrycode) values (97, 'Macao', 'MO'); insert into country (id, countryname, countrycode) values (98, 'Madagascar', 'MG'); insert into country (id, countryname, countrycode) values (99, 'Malawi', 'MW'); insert into country (id, countryname, countrycode) values (100, 'Malaysia', 'MY'); insert into country (id, countryname, countrycode) values (101, 'Maldives', 'MV'); insert into country (id, countryname, countrycode) values (102, 'Mali', 'ML'); insert into country (id, countryname, countrycode) values (103, 'Malta', 'MT'); insert into country (id, countryname, countrycode) values (104, 'Mauritius', 'MU'); insert into country (id, countryname, countrycode) values (105, 'Mexico', 'MX'); insert into country (id, countryname, countrycode) values (106, 'Moldova, Republic of', 'MD'); insert into country (id, countryname, countrycode) values (107, 'Monaco', 'MC'); insert into country (id, countryname, countrycode) values (108, 'Mongolia', 'MN'); insert into country (id, countryname, countrycode) values (109, 'Montserrat Is', 'MS'); insert into country (id, countryname, countrycode) values (110, 'Morocco', 'MA'); insert into country (id, countryname, countrycode) values (111, 'Mozambique', 'MZ'); insert into country (id, countryname, countrycode) values (112, 'Namibia', 'NA'); insert into country (id, countryname, countrycode) values (113, 'Nauru', 'NR'); insert into country (id, countryname, countrycode) values (114, 'Nepal', 'NP'); insert into country (id, countryname, countrycode) values (115, 'Netherlands', 'NL'); insert into country (id, countryname, countrycode) values (116, 'New Zealand', 'NZ'); insert into country (id, countryname, countrycode) values (117, 'Nicaragua', 'NI'); insert into country (id, countryname, countrycode) values (118, 'Niger', 'NE'); insert into country (id, countryname, countrycode) values (119, 'Nigeria', 'NG'); insert into country (id, countryname, countrycode) values (120, 'North Korea', 'KP'); insert into country (id, countryname, countrycode) values (121, 'Norway', 'NO'); insert into country (id, countryname, countrycode) values (122, 'Oman', 'OM'); insert into country (id, countryname, countrycode) values (123, 'Pakistan', 'PK'); insert into country (id, countryname, countrycode) values (124, 'Panama', 'PA'); insert into country (id, countryname, countrycode) values (125, 'Papua New Cuinea', 'PG'); insert into country (id, countryname, countrycode) values (126, 'Paraguay', 'PY'); insert into country (id, countryname, countrycode) values (127, 'Peru', 'PE'); insert into country (id, countryname, countrycode) values (128, 'Philippines', 'PH'); insert into country (id, countryname, countrycode) values (129, 'Poland', 'PL'); insert into country (id, countryname, countrycode) values (130, 'French Polynesia', 'PF'); insert into country (id, countryname, countrycode) values (131, 'Portugal', 'PT'); insert into country (id, countryname, countrycode) values (132, 'Puerto Rico', 'PR'); insert into country (id, countryname, countrycode) values (133, 'Qatar', 'QA'); insert into country (id, countryname, countrycode) values (134, 'Romania', 'RO'); insert into country (id, countryname, countrycode) values (135, 'Russia', 'RU'); insert into country (id, countryname, countrycode) values (136, 'Saint Lueia', 'LC'); insert into country (id, countryname, countrycode) values (137, 'Saint Vincent', 'VC'); insert into country (id, countryname, countrycode) values (138, 'San Marino', 'SM'); insert into country (id, countryname, countrycode) values (139, 'Sao Tome and Principe', 'ST'); insert into country (id, countryname, countrycode) values (140, 'Saudi Arabia', 'SA'); insert into country (id, countryname, countrycode) values (141, 'Senegal', 'SN'); insert into country (id, countryname, countrycode) values (142, 'Seychelles', 'SC'); insert into country (id, countryname, countrycode) values (143, 'Sierra Leone', 'SL'); insert into country (id, countryname, countrycode) values (144, 'Singapore', 'SG'); insert into country (id, countryname, countrycode) values (145, 'Slovakia', 'SK'); insert into country (id, countryname, countrycode) values (146, 'Slovenia', 'SI'); insert into country (id, countryname, countrycode) values (147, 'Solomon Is', 'SB'); insert into country (id, countryname, countrycode) values (148, 'Somali', 'SO'); insert into country (id, countryname, countrycode) values (149, 'South Africa', 'ZA'); insert into country (id, countryname, countrycode) values (150, 'Spain', 'ES'); insert into country (id, countryname, countrycode) values (151, 'Sri Lanka', 'LK'); insert into country (id, countryname, countrycode) values (152, 'St.Lucia', 'LC'); insert into country (id, countryname, countrycode) values (153, 'St.Vincent', 'VC'); insert into country (id, countryname, countrycode) values (154, 'Sudan', 'SD'); insert into country (id, countryname, countrycode) values (155, 'Suriname', 'SR'); insert into country (id, countryname, countrycode) values (156, 'Swaziland', 'SZ'); insert into country (id, countryname, countrycode) values (157, 'Sweden', 'SE'); insert into country (id, countryname, countrycode) values (158, 'Switzerland', 'CH'); insert into country (id, countryname, countrycode) values (159, 'Syria', 'SY'); insert into country (id, countryname, countrycode) values (160, 'Taiwan', 'TW'); insert into country (id, countryname, countrycode) values (161, 'Tajikstan', 'TJ'); insert into country (id, countryname, countrycode) values (162, 'Tanzania', 'TZ'); insert into country (id, countryname, countrycode) values (163, 'Thailand', 'TH'); insert into country (id, countryname, countrycode) values (164, 'Togo', 'TG'); insert into country (id, countryname, countrycode) values (165, 'Tonga', 'TO'); insert into country (id, countryname, countrycode) values (166, 'Trinidad and Tobago', 'TT'); insert into country (id, countryname, countrycode) values (167, 'Tunisia', 'TN'); insert into country (id, countryname, countrycode) values (168, 'Turkey', 'TR'); insert into country (id, countryname, countrycode) values (169, 'Turkmenistan', 'TM'); insert into country (id, countryname, countrycode) values (170, 'Uganda', 'UG'); insert into country (id, countryname, countrycode) values (171, 'Ukraine', 'UA'); insert into country (id, countryname, countrycode) values (172, 'United Arab Emirates', 'AE'); insert into country (id, countryname, countrycode) values (173, 'United Kiongdom', 'GB'); insert into country (id, countryname, countrycode) values (174, 'United States of America', 'US'); insert into country (id, countryname, countrycode) values (175, 'Uruguay', 'UY'); insert into country (id, countryname, countrycode) values (176, 'Uzbekistan', 'UZ'); insert into country (id, countryname, countrycode) values (177, 'Venezuela', 'VE'); insert into country (id, countryname, countrycode) values (178, 'Vietnam', 'VN'); insert into country (id, countryname, countrycode) values (179, 'Yemen', 'YE'); insert into country (id, countryname, countrycode) values (180, 'Yugoslavia', 'YU'); insert into country (id, countryname, countrycode) values (181, 'Zimbabwe', 'ZW'); insert into country (id, countryname, countrycode) values (182, 'Zaire', 'ZR'); insert into country (id, countryname, countrycode) values (183, 'Zambia', 'ZM'); ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/pom.xml ================================================ 4.0.0 tk.mybatis mapper-spring-boot-samples ${revision} mapper-spring-boot-sample-xml jar mapper-spring-boot-sample-xml org.slf4j slf4j-api runtime tk.mybatis mapper-spring-boot-starter com.h2database h2 runtime org.springframework.boot spring-boot-maven-plugin ${spring-boot.version} ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample; import org.apache.ibatis.annotations.Mapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import tk.mybatis.sample.domain.Country; import tk.mybatis.sample.mapper.CountryMapper; import tk.mybatis.spring.annotation.MapperScan; import java.util.List; @SpringBootApplication //@MapperScan(basePackages = "tk.mybatis.sample", annotationClass = Mapper.class ) public class SampleXmlApplication implements CommandLineRunner { @Autowired private CountryMapper countryMapper; public static void main(String[] args) { SpringApplication.run(SampleXmlApplication.class, args); } @Override public void run(String... args) throws Exception { Country c = countryMapper.selectByPrimaryKey(1); System.out.println("Key : 1, Country Name: " + c.getCountryname()); c.setId(1000L); c.setCountryname("新名字"); countryMapper.insert(c); System.out.println("New Key: " + c.getId()); List countries = countryMapper.selectAll(); for (Country country : countries) { System.out.println("Country Name: " + country.getCountryname()); } } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/domain/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample.domain; import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.annotation.ColumnType; import jakarta.persistence.Id; import java.io.Serializable; /** * Description: Country * Author: liuzh * Update: liuzh(2014-06-06 13:38) */ public class Country implements Serializable { private static final long serialVersionUID = 6569081236403751407L; @Id @ColumnType(jdbcType = JdbcType.BIGINT) private Long id; private String countryname; private String countrycode; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/mapper/BaseMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample.mapper; import tk.mybatis.mapper.annotation.RegisterMapper; import tk.mybatis.mapper.common.Mapper; /** * @author liuzh * @since 2017/1/2. */ @RegisterMapper public interface BaseMapper extends Mapper { } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/mapper/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.sample.mapper; import tk.mybatis.sample.domain.Country; import java.util.List; /** * @author Eduardo Macarron */ public interface CountryMapper extends BaseMapper { List findAll(); } ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml ================================================ # # The MIT License (MIT) # # Copyright (c) 2017 abel533@gmail.com # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # spring: sql: init: schema-locations: classpath:import.sql mybatis: config-location: mybatis-config.xml base-packages: tk.mybatis.sample.mapper logging: level: root: DEBUG tk.mybatis.sample.mapper: TRACE mapper: not-empty: true before: true mappers: - tk.mybatis.sample.mapper.BaseMapper - tk.mybatis.mapper.common.Mapper ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/import.sql ================================================ drop table country if exists; create table country ( id int primary key auto_increment, countryname varchar(32), countrycode varchar(2) ); insert into country (id, countryname, countrycode) values (1, 'Angola', 'AO'); insert into country (id, countryname, countrycode) values (2, 'Afghanistan', 'AF'); insert into country (id, countryname, countrycode) values (3, 'Albania', 'AL'); insert into country (id, countryname, countrycode) values (4, 'Algeria', 'DZ'); insert into country (id, countryname, countrycode) values (5, 'Andorra', 'AD'); insert into country (id, countryname, countrycode) values (6, 'Anguilla', 'AI'); insert into country (id, countryname, countrycode) values (7, 'Antigua and Barbuda', 'AG'); insert into country (id, countryname, countrycode) values (8, 'Argentina', 'AR'); insert into country (id, countryname, countrycode) values (9, 'Armenia', 'AM'); insert into country (id, countryname, countrycode) values (10, 'Australia', 'AU'); insert into country (id, countryname, countrycode) values (11, 'Austria', 'AT'); insert into country (id, countryname, countrycode) values (12, 'Azerbaijan', 'AZ'); insert into country (id, countryname, countrycode) values (13, 'Bahamas', 'BS'); insert into country (id, countryname, countrycode) values (14, 'Bahrain', 'BH'); insert into country (id, countryname, countrycode) values (15, 'Bangladesh', 'BD'); insert into country (id, countryname, countrycode) values (16, 'Barbados', 'BB'); insert into country (id, countryname, countrycode) values (17, 'Belarus', 'BY'); insert into country (id, countryname, countrycode) values (18, 'Belgium', 'BE'); insert into country (id, countryname, countrycode) values (19, 'Belize', 'BZ'); insert into country (id, countryname, countrycode) values (20, 'Benin', 'BJ'); insert into country (id, countryname, countrycode) values (21, 'Bermuda Is.', 'BM'); insert into country (id, countryname, countrycode) values (22, 'Bolivia', 'BO'); insert into country (id, countryname, countrycode) values (23, 'Botswana', 'BW'); insert into country (id, countryname, countrycode) values (24, 'Brazil', 'BR'); insert into country (id, countryname, countrycode) values (25, 'Brunei', 'BN'); insert into country (id, countryname, countrycode) values (26, 'Bulgaria', 'BG'); insert into country (id, countryname, countrycode) values (27, 'Burkina-faso', 'BF'); insert into country (id, countryname, countrycode) values (28, 'Burma', 'MM'); insert into country (id, countryname, countrycode) values (29, 'Burundi', 'BI'); insert into country (id, countryname, countrycode) values (30, 'Cameroon', 'CM'); insert into country (id, countryname, countrycode) values (31, 'Canada', 'CA'); insert into country (id, countryname, countrycode) values (32, 'Central African Republic', 'CF'); insert into country (id, countryname, countrycode) values (33, 'Chad', 'TD'); insert into country (id, countryname, countrycode) values (34, 'Chile', 'CL'); insert into country (id, countryname, countrycode) values (35, 'China', 'CN'); insert into country (id, countryname, countrycode) values (36, 'Colombia', 'CO'); insert into country (id, countryname, countrycode) values (37, 'Congo', 'CG'); insert into country (id, countryname, countrycode) values (38, 'Cook Is.', 'CK'); insert into country (id, countryname, countrycode) values (39, 'Costa Rica', 'CR'); insert into country (id, countryname, countrycode) values (40, 'Cuba', 'CU'); insert into country (id, countryname, countrycode) values (41, 'Cyprus', 'CY'); insert into country (id, countryname, countrycode) values (42, 'Czech Republic', 'CZ'); insert into country (id, countryname, countrycode) values (43, 'Denmark', 'DK'); insert into country (id, countryname, countrycode) values (44, 'Djibouti', 'DJ'); insert into country (id, countryname, countrycode) values (45, 'Dominica Rep.', 'DO'); insert into country (id, countryname, countrycode) values (46, 'Ecuador', 'EC'); insert into country (id, countryname, countrycode) values (47, 'Egypt', 'EG'); insert into country (id, countryname, countrycode) values (48, 'EI Salvador', 'SV'); insert into country (id, countryname, countrycode) values (49, 'Estonia', 'EE'); insert into country (id, countryname, countrycode) values (50, 'Ethiopia', 'ET'); insert into country (id, countryname, countrycode) values (51, 'Fiji', 'FJ'); insert into country (id, countryname, countrycode) values (52, 'Finland', 'FI'); insert into country (id, countryname, countrycode) values (53, 'France', 'FR'); insert into country (id, countryname, countrycode) values (54, 'French Guiana', 'GF'); insert into country (id, countryname, countrycode) values (55, 'Gabon', 'GA'); insert into country (id, countryname, countrycode) values (56, 'Gambia', 'GM'); insert into country (id, countryname, countrycode) values (57, 'Georgia', 'GE'); insert into country (id, countryname, countrycode) values (58, 'Germany', 'DE'); insert into country (id, countryname, countrycode) values (59, 'Ghana', 'GH'); insert into country (id, countryname, countrycode) values (60, 'Gibraltar', 'GI'); insert into country (id, countryname, countrycode) values (61, 'Greece', 'GR'); insert into country (id, countryname, countrycode) values (62, 'Grenada', 'GD'); insert into country (id, countryname, countrycode) values (63, 'Guam', 'GU'); insert into country (id, countryname, countrycode) values (64, 'Guatemala', 'GT'); insert into country (id, countryname, countrycode) values (65, 'Guinea', 'GN'); insert into country (id, countryname, countrycode) values (66, 'Guyana', 'GY'); insert into country (id, countryname, countrycode) values (67, 'Haiti', 'HT'); insert into country (id, countryname, countrycode) values (68, 'Honduras', 'HN'); insert into country (id, countryname, countrycode) values (69, 'Hongkong', 'HK'); insert into country (id, countryname, countrycode) values (70, 'Hungary', 'HU'); insert into country (id, countryname, countrycode) values (71, 'Iceland', 'IS'); insert into country (id, countryname, countrycode) values (72, 'India', 'IN'); insert into country (id, countryname, countrycode) values (73, 'Indonesia', 'ID'); insert into country (id, countryname, countrycode) values (74, 'Iran', 'IR'); insert into country (id, countryname, countrycode) values (75, 'Iraq', 'IQ'); insert into country (id, countryname, countrycode) values (76, 'Ireland', 'IE'); insert into country (id, countryname, countrycode) values (77, 'Israel', 'IL'); insert into country (id, countryname, countrycode) values (78, 'Italy', 'IT'); insert into country (id, countryname, countrycode) values (79, 'Jamaica', 'JM'); insert into country (id, countryname, countrycode) values (80, 'Japan', 'JP'); insert into country (id, countryname, countrycode) values (81, 'Jordan', 'JO'); insert into country (id, countryname, countrycode) values (82, 'Kampuchea (Cambodia )', 'KH'); insert into country (id, countryname, countrycode) values (83, 'Kazakstan', 'KZ'); insert into country (id, countryname, countrycode) values (84, 'Kenya', 'KE'); insert into country (id, countryname, countrycode) values (85, 'Korea', 'KR'); insert into country (id, countryname, countrycode) values (86, 'Kuwait', 'KW'); insert into country (id, countryname, countrycode) values (87, 'Kyrgyzstan', 'KG'); insert into country (id, countryname, countrycode) values (88, 'Laos', 'LA'); insert into country (id, countryname, countrycode) values (89, 'Latvia', 'LV'); insert into country (id, countryname, countrycode) values (90, 'Lebanon', 'LB'); insert into country (id, countryname, countrycode) values (91, 'Lesotho', 'LS'); insert into country (id, countryname, countrycode) values (92, 'Liberia', 'LR'); insert into country (id, countryname, countrycode) values (93, 'Libya', 'LY'); insert into country (id, countryname, countrycode) values (94, 'Liechtenstein', 'LI'); insert into country (id, countryname, countrycode) values (95, 'Lithuania', 'LT'); insert into country (id, countryname, countrycode) values (96, 'Luxembourg', 'LU'); insert into country (id, countryname, countrycode) values (97, 'Macao', 'MO'); insert into country (id, countryname, countrycode) values (98, 'Madagascar', 'MG'); insert into country (id, countryname, countrycode) values (99, 'Malawi', 'MW'); insert into country (id, countryname, countrycode) values (100, 'Malaysia', 'MY'); insert into country (id, countryname, countrycode) values (101, 'Maldives', 'MV'); insert into country (id, countryname, countrycode) values (102, 'Mali', 'ML'); insert into country (id, countryname, countrycode) values (103, 'Malta', 'MT'); insert into country (id, countryname, countrycode) values (104, 'Mauritius', 'MU'); insert into country (id, countryname, countrycode) values (105, 'Mexico', 'MX'); insert into country (id, countryname, countrycode) values (106, 'Moldova, Republic of', 'MD'); insert into country (id, countryname, countrycode) values (107, 'Monaco', 'MC'); insert into country (id, countryname, countrycode) values (108, 'Mongolia', 'MN'); insert into country (id, countryname, countrycode) values (109, 'Montserrat Is', 'MS'); insert into country (id, countryname, countrycode) values (110, 'Morocco', 'MA'); insert into country (id, countryname, countrycode) values (111, 'Mozambique', 'MZ'); insert into country (id, countryname, countrycode) values (112, 'Namibia', 'NA'); insert into country (id, countryname, countrycode) values (113, 'Nauru', 'NR'); insert into country (id, countryname, countrycode) values (114, 'Nepal', 'NP'); insert into country (id, countryname, countrycode) values (115, 'Netherlands', 'NL'); insert into country (id, countryname, countrycode) values (116, 'New Zealand', 'NZ'); insert into country (id, countryname, countrycode) values (117, 'Nicaragua', 'NI'); insert into country (id, countryname, countrycode) values (118, 'Niger', 'NE'); insert into country (id, countryname, countrycode) values (119, 'Nigeria', 'NG'); insert into country (id, countryname, countrycode) values (120, 'North Korea', 'KP'); insert into country (id, countryname, countrycode) values (121, 'Norway', 'NO'); insert into country (id, countryname, countrycode) values (122, 'Oman', 'OM'); insert into country (id, countryname, countrycode) values (123, 'Pakistan', 'PK'); insert into country (id, countryname, countrycode) values (124, 'Panama', 'PA'); insert into country (id, countryname, countrycode) values (125, 'Papua New Cuinea', 'PG'); insert into country (id, countryname, countrycode) values (126, 'Paraguay', 'PY'); insert into country (id, countryname, countrycode) values (127, 'Peru', 'PE'); insert into country (id, countryname, countrycode) values (128, 'Philippines', 'PH'); insert into country (id, countryname, countrycode) values (129, 'Poland', 'PL'); insert into country (id, countryname, countrycode) values (130, 'French Polynesia', 'PF'); insert into country (id, countryname, countrycode) values (131, 'Portugal', 'PT'); insert into country (id, countryname, countrycode) values (132, 'Puerto Rico', 'PR'); insert into country (id, countryname, countrycode) values (133, 'Qatar', 'QA'); insert into country (id, countryname, countrycode) values (134, 'Romania', 'RO'); insert into country (id, countryname, countrycode) values (135, 'Russia', 'RU'); insert into country (id, countryname, countrycode) values (136, 'Saint Lueia', 'LC'); insert into country (id, countryname, countrycode) values (137, 'Saint Vincent', 'VC'); insert into country (id, countryname, countrycode) values (138, 'San Marino', 'SM'); insert into country (id, countryname, countrycode) values (139, 'Sao Tome and Principe', 'ST'); insert into country (id, countryname, countrycode) values (140, 'Saudi Arabia', 'SA'); insert into country (id, countryname, countrycode) values (141, 'Senegal', 'SN'); insert into country (id, countryname, countrycode) values (142, 'Seychelles', 'SC'); insert into country (id, countryname, countrycode) values (143, 'Sierra Leone', 'SL'); insert into country (id, countryname, countrycode) values (144, 'Singapore', 'SG'); insert into country (id, countryname, countrycode) values (145, 'Slovakia', 'SK'); insert into country (id, countryname, countrycode) values (146, 'Slovenia', 'SI'); insert into country (id, countryname, countrycode) values (147, 'Solomon Is', 'SB'); insert into country (id, countryname, countrycode) values (148, 'Somali', 'SO'); insert into country (id, countryname, countrycode) values (149, 'South Africa', 'ZA'); insert into country (id, countryname, countrycode) values (150, 'Spain', 'ES'); insert into country (id, countryname, countrycode) values (151, 'Sri Lanka', 'LK'); insert into country (id, countryname, countrycode) values (152, 'St.Lucia', 'LC'); insert into country (id, countryname, countrycode) values (153, 'St.Vincent', 'VC'); insert into country (id, countryname, countrycode) values (154, 'Sudan', 'SD'); insert into country (id, countryname, countrycode) values (155, 'Suriname', 'SR'); insert into country (id, countryname, countrycode) values (156, 'Swaziland', 'SZ'); insert into country (id, countryname, countrycode) values (157, 'Sweden', 'SE'); insert into country (id, countryname, countrycode) values (158, 'Switzerland', 'CH'); insert into country (id, countryname, countrycode) values (159, 'Syria', 'SY'); insert into country (id, countryname, countrycode) values (160, 'Taiwan', 'TW'); insert into country (id, countryname, countrycode) values (161, 'Tajikstan', 'TJ'); insert into country (id, countryname, countrycode) values (162, 'Tanzania', 'TZ'); insert into country (id, countryname, countrycode) values (163, 'Thailand', 'TH'); insert into country (id, countryname, countrycode) values (164, 'Togo', 'TG'); insert into country (id, countryname, countrycode) values (165, 'Tonga', 'TO'); insert into country (id, countryname, countrycode) values (166, 'Trinidad and Tobago', 'TT'); insert into country (id, countryname, countrycode) values (167, 'Tunisia', 'TN'); insert into country (id, countryname, countrycode) values (168, 'Turkey', 'TR'); insert into country (id, countryname, countrycode) values (169, 'Turkmenistan', 'TM'); insert into country (id, countryname, countrycode) values (170, 'Uganda', 'UG'); insert into country (id, countryname, countrycode) values (171, 'Ukraine', 'UA'); insert into country (id, countryname, countrycode) values (172, 'United Arab Emirates', 'AE'); insert into country (id, countryname, countrycode) values (173, 'United Kiongdom', 'GB'); insert into country (id, countryname, countrycode) values (174, 'United States of America', 'US'); insert into country (id, countryname, countrycode) values (175, 'Uruguay', 'UY'); insert into country (id, countryname, countrycode) values (176, 'Uzbekistan', 'UZ'); insert into country (id, countryname, countrycode) values (177, 'Venezuela', 'VE'); insert into country (id, countryname, countrycode) values (178, 'Vietnam', 'VN'); insert into country (id, countryname, countrycode) values (179, 'Yemen', 'YE'); insert into country (id, countryname, countrycode) values (180, 'Yugoslavia', 'YU'); insert into country (id, countryname, countrycode) values (181, 'Zimbabwe', 'ZW'); insert into country (id, countryname, countrycode) values (182, 'Zaire', 'ZR'); insert into country (id, countryname, countrycode) values (183, 'Zambia', 'ZM'); ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/mybatis-config.xml ================================================ ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/tk/mybatis/sample/mapper/CountryMapper.xml ================================================ ================================================ FILE: spring-boot-starter/mapper-spring-boot-samples/pom.xml ================================================ 4.0.0 tk.mybatis mapper-spring-boot ${revision} mapper-spring-boot-samples pom mapper-spring-boot-samples mapper-spring-boot-sample-annotation mapper-spring-boot-sample-xml ognl ognl 3.1.2 javassist javassist org.javassist javassist 3.20.0-GA ================================================ FILE: spring-boot-starter/mapper-spring-boot-starter/pom.xml ================================================ 4.0.0 tk.mybatis mapper-spring-boot ${revision} mapper-spring-boot-starter mapper-spring-boot-starter org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-jdbc org.mybatis mybatis org.mybatis mybatis-spring tk.mybatis mapper-core tk.mybatis mapper-base tk.mybatis mapper-weekend tk.mybatis mapper-spring tk.mybatis mapper-extra tk.mybatis mapper-spring-boot-autoconfigure ================================================ FILE: spring-boot-starter/mapper-spring-boot-starter/src/main/resources/META-INF/spring.provides ================================================ provides: mapper-spring-boot-autoconfigure,mapper,mybatis-spring-boot-autoconfigure,mybatis,mybatis-spring ================================================ FILE: spring-boot-starter/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-spring-boot pom mapper-spring-boot Spring Boot Support for Mapper https://github.com/abel533/mapper-boot-starter/ mapper-spring-boot-autoconfigure mapper-spring-boot-starter mapper-spring-boot-samples 4.0.0 4.0.2 spring-snapshots https://repo.spring.io/snapshot true spring-milestones https://repo.spring.io/milestone spring-snapshots https://repo.spring.io/snapshot spring-milestones https://repo.spring.io/milestone tk.mybatis mapper-core ${project.version} tk.mybatis mapper-base ${project.version} tk.mybatis mapper-weekend ${project.version} tk.mybatis mapper-spring ${project.version} tk.mybatis mapper-extra ${project.version} org.mybatis mybatis-spring ${mybatis-spring.version} tk.mybatis mapper-spring-boot-autoconfigure ${project.version} tk.mybatis mapper-spring-boot-starter ${project.version} org.springframework.boot spring-boot-dependencies ${spring-boot.version} pom import ================================================ FILE: weekend/README.md ================================================ # mapper-weekend [![Maven central](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-weekend/badge.svg)](https://maven-badges.herokuapp.com/maven-central/tk.mybatis/mapper-weekend) 作者:[liuyuyu](https://github.com/liuyuyu) # 支持 jdk 8+ ## 说明 在经过作者同意后,对项目包名和 Maven 的GAV信息进行修改,将该项目打包上传到 Maven 官方仓库。 虽然这个是一个独立的项目,但是大家在使用过程中,不需要引用这个项目。 这个独立项目是以 jdk 8 进行打包的,打包后的 class 会被集成到通用 Mapper 中(主代码使用 jdk 6 编译)。 ## 基于 https://github.com/abel533/Mapper 做的增强 可以在 `Example.Criteria` 的条件方法里传 lambada(再也不用担心改数据库了......)。 栗子: ```java UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Weekend weekend = Weekend.of(User.class); weekend.weekendCriteria() .andIsNull(User::getId) .andBetween(User::getId,0,10) .andIn(User::getUserName, Arrays.asList("a","b","c")); ``` 和(作者: [XuYin](https://github.com/chinaerserver)) ```java CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom().andLike(Country::getCountryname, "China")).build()); ``` ================================================ FILE: weekend/pom.xml ================================================ 4.0.0 tk.mybatis mapper-modules ${revision} mapper-weekend weekend Mybatis通用Mapper扩展 - weekend liuyuyu liuyuyu2333@gmail.com abel533 abel533@gmail.com chinaerserver chinaerserver@gmail.com org.mybatis mybatis tk.mybatis mapper-core ${project.version} provided tk.mybatis mapper-base ${project.version} test ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/Fn.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import java.io.Serializable; import java.util.function.Function; /** * @author Frank */ public interface Fn extends Function, Serializable { } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/SqlCriteriaHelper.java ================================================ package tk.mybatis.mapper.weekend; import tk.mybatis.mapper.util.Sqls; import tk.mybatis.mapper.weekend.reflection.Reflections; import java.util.Optional; /** * sql 条件语句 * * @author Cheng.Wei * @date 2019-04-15 10:26 */ public class SqlCriteriaHelper implements tk.mybatis.mapper.entity.SqlsCriteria { private Sqls.Criteria criteria; private SqlCriteriaHelper() { this.criteria = new Sqls.Criteria(); } public static SqlCriteriaHelper custom(Class clazz) { return new SqlCriteriaHelper(); } /** * AND column IS NULL * * @param fn * @return */ public SqlCriteriaHelper andIsNull(Fn fn) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), "is null", "and")); return this; } /** * AND column IS NOT NULL * * @param fn * @return */ public SqlCriteriaHelper andIsNotNull(Fn fn) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), "is not null", "and")); return this; } /** * AND column = value * 当value=null则不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andEqualTo(Fn fn, Object value) { return this.andEqualTo(fn, value, false); } /** * AND column = value * * @param fn * @param value * @param required false 当value=null 则不参与查询 ; * true 当value = null 则转 is null 查询: AND column is null * @return */ public SqlCriteriaHelper andEqualTo(Fn fn, Object value, boolean required) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "=", "and")); } else { if (required) { // null属性查询 转 is null this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), "is null", "and")); } } return this; } /** * AND column != value * 默认 value=null 则不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andNotEqualTo(Fn fn, Object value) { return this.andNotEqualTo(fn, value, false); } /** * AND column != value * * @param fn * @param value * @param required false 当value=null 则不参与查询 ; * true 当value = null 则转 is not null 查询 : AND column is not null * @return */ public SqlCriteriaHelper andNotEqualTo(Fn fn, Object value, boolean required) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "<>", "and")); } else { if (required) { //转非空查询 this.andIsNotNull(fn); } } return this; } /** * AND column > value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andGreaterThan(Fn fn, Object value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, ">", "and")); } return this; } /** * AND column >= value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andGreaterThanOrEqualTo(Fn fn, Object value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, ">=", "and")); } return this; } /** * AND column < value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andLessThan(Fn fn, Object value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "<", "and")); } return this; } /** * AND column <= value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andLessThanOrEqualTo(Fn fn, Object value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "<=", "and")); } return this; } /** * AND column IN (#{item.value}) * 当 values = null 则当前属性不参与查询 * * @param fn * @param values * @return */ public SqlCriteriaHelper andIn(Fn fn, Iterable values) { if (Optional.ofNullable(values).isPresent() && values.iterator().hasNext()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), values, "in", "and")); } return this; } /** * AND column NOT IN (#{item.value}) * 当 values = null 则当前属性不参与查询 * * @param fn * @param values * @return */ public SqlCriteriaHelper andNotIn(Fn fn, Iterable values) { if (Optional.ofNullable(values).isPresent() && values.iterator().hasNext()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), values, "not in", "and")); } return this; } /** * AND column BETWEEN value1 AND value2 * 当 value1 或 value2 为空 则当前属性不参与查询 * * @param fn * @param value1 * @param value2 * @return */ public SqlCriteriaHelper andBetween(Fn fn, Object value1, Object value2) { if (Optional.ofNullable(value1).isPresent() && Optional.ofNullable(value2).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value1, value2, "between", "and")); } return this; } /** * AND column NOT BETWEEN value1 AND value2 * 当 value1 或 value2 为空 则当前属性不参与查询 * * @param fn * @param value1 * @param value2 * @return */ public SqlCriteriaHelper andNotBetween(Fn fn, Object value1, Object value2) { if (Optional.ofNullable(value1).isPresent() && Optional.ofNullable(value2).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value1, value2, "not between", "and")); } return this; } /** * AND column LIKE %value% * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andLike(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "like", "and")); } return this; } /** * AND column LIKE %value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andLikeLeft(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "like", "and")); } return this; } /** * AND column LIKE value% * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andLikeRight(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "like", "and")); } return this; } /** * AND column NOT LIKE %value% * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andNotLike(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "not like", "and")); } return this; } /** * AND column NOT LIKE %value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andNotLikeLeft(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "not like", "and")); } return this; } /** * AND column NOT LIKE value% * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper andNotLikeRight(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "not like", "and")); } return this; } /** * OR column IS NULL * 当 value = null 则当前属性不参与查询 * * @param fn * @return */ public SqlCriteriaHelper orIsNull(Fn fn) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), "is null", "or")); return this; } /** * OR column IS NOT NULL * 当 value = null 则当前属性不参与查询 * * @param fn * @return */ public SqlCriteriaHelper orIsNotNull(Fn fn) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), "is not null", "or")); return this; } /** * OR column = value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orEqualTo(Fn fn, Object value) { return this.orEqualTo(fn, value, false); } /** * OR column = value * 当request = true 且 value = null时 转 #{@link #orIsNull(Fn)} * * @param fn * @param value * @param required * @return */ public SqlCriteriaHelper orEqualTo(Fn fn, Object value, boolean required) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "=", "or")); } else { if (required) { //转 or null this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), "is null", "or")); } } return this; } /** * OR column <> value * 当value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orNotEqualTo(Fn fn, Object value) { return this.orNotEqualTo(fn, value, false); } /** * OR column <> value * 当request = true 且 value = null时 转 #{@link #orIsNotNull(Fn)} * * @param fn * @param value * @param required * @return */ public SqlCriteriaHelper orNotEqualTo(Fn fn, Object value, boolean required) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "<>", "or")); } else { if (required) { // 转 or is not null this.orIsNotNull(fn); } } return this; } /** * OR column > value * 当value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orGreaterThan(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, ">", "or")); } return this; } /** * OR column >= value * 当value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orGreaterThanOrEqualTo(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, ">=", "or")); } return this; } /** * OR column < value * 当value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orLessThan(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "<", "or")); } return this; } /** * OR column <= value * 当value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orLessThanOrEqualTo(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "<=", "or")); } return this; } /** * OR column IN (#{item.value}) * 当value = null 则当前属性不参与查询 * * @param fn * @param values * @return */ public SqlCriteriaHelper orIn(Fn fn, Iterable values) { if (Optional.ofNullable(values).isPresent() && values.iterator().hasNext()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), values, "in", "or")); } return this; } /** * OR column NOT IN (#{item.value}) * 当value = null 则当前属性不参与查询 * * @param fn * @param values * @return */ public SqlCriteriaHelper orNotIn(Fn fn, Iterable values) { if (Optional.ofNullable(values).isPresent() && values.iterator().hasNext()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), values, "not in", "or")); } return this; } /** * OR column BETWEEN value1 AND value2 * 当 value1 或 value2 为空 则当前属性不参与查询 * * @param fn * @param value1 * @param value2 * @return */ public SqlCriteriaHelper orBetween(Fn fn, Object value1, Object value2) { if (Optional.ofNullable(value1).isPresent() && Optional.ofNullable(value2).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value1, value2, "between", "or")); } return this; } /** * OR column NOT BETWEEN value1 AND value2 * 当 value1 或 value2 为空 则当前属性不参与查询 * * @param fn * @param value1 * @param value2 * @return */ public SqlCriteriaHelper orNotBetween(Fn fn, Object value1, Object value2) { if (Optional.ofNullable(value1).isPresent() && Optional.ofNullable(value2).isPresent()) { this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value1, value2, "not between", "or")); } return this; } /** * OR column LIKE value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orLike(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "like", "or")); } return this; } /** * OR column LIKE %value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orLikeLeft(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "like", "or")); } return this; } /** * OR column LIKE value% * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orLikeRight(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "like", "or")); } return this; } /** * OR column NOT LIKE value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orNotLike(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "not like", "or")); } return this; } /** * OR column NOT LIKE %value * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orNotLikeLeft(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = "%" + value; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "not like", "or")); } return this; } /** * OR column NOT LIKE value% * 当 value = null 则当前属性不参与查询 * * @param fn * @param value * @return */ public SqlCriteriaHelper orNotLikeRight(Fn fn, String value) { if (Optional.ofNullable(value).isPresent()) { value = value + "%"; this.criteria.getCriterions().add(new Sqls.Criterion(Reflections.fnToFieldName(fn), value, "not like", "or")); } return this; } @Override public Sqls.Criteria getCriteria() { return criteria; } } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/Weekend.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import tk.mybatis.mapper.weekend.reflection.Reflections; import java.util.stream.Stream; /** * @author Frank */ public class Weekend extends tk.mybatis.mapper.entity.Example { public Weekend(Class entityClass) { super(entityClass); } public Weekend(Class entityClass, boolean exists) { super(entityClass, exists); } public Weekend(Class entityClass, boolean exists, boolean notNull) { super(entityClass, exists, notNull); } public static Weekend of(Class clazz, Boolean exists, boolean notNull) { return new Weekend(clazz, exists, notNull); } public static Weekend of(Class clazz, Boolean exists) { return new Weekend(clazz, exists, Boolean.FALSE); } public static Weekend of(Class clazz) { return new Weekend(clazz, Boolean.TRUE); } public WeekendCriteria createCriteriaAddOn() { WeekendCriteria weekendCriteria = new WeekendCriteria<>(this.propertyMap, this.exists, this.notNull); return weekendCriteria; } @Override protected Criteria createCriteriaInternal() { return this.createCriteriaAddOn(); } @SuppressWarnings("all") public WeekendCriteria weekendCriteria() { return (WeekendCriteria) this.createCriteria(); } /** * 排除查询字段,优先级低于 selectProperties * * @param fns 属性名的可变参数 * @return */ public Weekend excludeProperties(Fn... fns) { String[] properties = Stream.of(fns).map(Reflections::fnToFieldName).toArray(String[]::new); this.excludeProperties(properties); return this; } /** * 指定要查询的属性列 - 这里会自动映射到表字段 * * @param fns * @return */ public Weekend selectProperties(Fn... fns) { String[] properties = Stream.of(fns).map(Reflections::fnToFieldName).toArray(String[]::new); this.selectProperties(properties); return this; } public OrderBy orderBy(Fn fn) { return this.orderBy(Reflections.fnToFieldName(fn)); } public Weekend withDistinct(boolean distinct) { this.setDistinct(distinct); return this; } public Weekend withForUpdate(boolean forUpdate) { this.setForUpdate(forUpdate); return this; } public Weekend withCountProperty(Fn fn) { this.setCountProperty(Reflections.fnToFieldName(fn)); return this; } public Weekend withTableName(String tableName) { this.setTableName(tableName); return this; } } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/WeekendCriteria.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.entity.Example.Criteria; import tk.mybatis.mapper.weekend.reflection.Reflections; import java.util.Map; /** * @author Frank */ public class WeekendCriteria extends Criteria { protected WeekendCriteria(Map propertyMap, boolean exists, boolean notNull) { super(propertyMap, exists, notNull); } public WeekendCriteria andIsNull(Fn fn) { this.andIsNull(Reflections.fnToFieldName(fn)); return this; } public WeekendCriteria andIsNotNull(Fn fn) { super.andIsNotNull(Reflections.fnToFieldName(fn)); return this; } public WeekendCriteria andEqualTo(Fn fn, Object value) { super.andEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andNotEqualTo(Fn fn, Object value) { super.andNotEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andGreaterThan(Fn fn, Object value) { super.andGreaterThan(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andGreaterThanOrEqualTo(Fn fn, Object value) { super.andGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andLessThan(Fn fn, Object value) { super.andLessThan(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andLessThanOrEqualTo(Fn fn, Object value) { super.andLessThanOrEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andIn(Fn fn, Iterable values) { super.andIn(Reflections.fnToFieldName(fn), values); return this; } public WeekendCriteria andNotIn(Fn fn, Iterable values) { super.andNotIn(Reflections.fnToFieldName(fn), values); return this; } public WeekendCriteria andBetween(Fn fn, Object value1, Object value2) { super.andBetween(Reflections.fnToFieldName(fn), value1, value2); return this; } public WeekendCriteria andNotBetween(Fn fn, Object value1, Object value2) { super.andNotBetween(Reflections.fnToFieldName(fn), value1, value2); return this; } public WeekendCriteria andLike(Fn fn, String value) { super.andLike(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria andNotLike(Fn fn, String value) { super.andNotLike(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orIsNull(Fn fn) { super.orIsNull(Reflections.fnToFieldName(fn)); return this; } public WeekendCriteria orIsNotNull(Fn fn) { super.orIsNotNull(Reflections.fnToFieldName(fn)); return this; } public WeekendCriteria orEqualTo(Fn fn, Object value) { super.orEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orNotEqualTo(Fn fn, Object value) { super.orNotEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orGreaterThan(Fn fn, Object value) { super.orGreaterThan(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orGreaterThanOrEqualTo(Fn fn, Object value) { super.orGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orLessThan(Fn fn, Object value) { super.orLessThan(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orLessThanOrEqualTo(Fn fn, Object value) { super.orLessThanOrEqualTo(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orIn(Fn fn, Iterable values) { super.orIn(Reflections.fnToFieldName(fn), values); return this; } public WeekendCriteria orNotIn(Fn fn, Iterable values) { super.orNotIn(Reflections.fnToFieldName(fn), values); return this; } public WeekendCriteria orBetween(Fn fn, Object value1, Object value2) { super.orBetween(Reflections.fnToFieldName(fn), value1, value2); return this; } public WeekendCriteria orNotBetween(Fn fn, Object value1, Object value2) { super.orNotBetween(Reflections.fnToFieldName(fn), value1, value2); return this; } public WeekendCriteria orLike(Fn fn, String value) { super.orLike(Reflections.fnToFieldName(fn), value); return this; } public WeekendCriteria orNotLike(Fn fn, String value) { super.orNotLike(Reflections.fnToFieldName(fn), value); return this; } } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/WeekendSqls.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import tk.mybatis.mapper.util.Sqls; import tk.mybatis.mapper.util.Sqls.Criteria; import tk.mybatis.mapper.util.Sqls.Criterion; import tk.mybatis.mapper.weekend.reflection.Reflections; /** * @author XuYin */ public class WeekendSqls implements tk.mybatis.mapper.entity.SqlsCriteria { private Criteria criteria; private WeekendSqls() { this.criteria = new Sqls.Criteria(); } public static WeekendSqls custom() { return new WeekendSqls(); } public WeekendSqls andIsNull(String property) { this.criteria.getCriterions().add(new Criterion(property, "is null", "and")); return this; } public WeekendSqls andIsNull(Fn fn) { return this.andIsNull(Reflections.fnToFieldName(fn)); } public WeekendSqls andIsNotNull(String property) { this.criteria.getCriterions().add(new Criterion(property, "is not null", "and")); return this; } public WeekendSqls andIsNotNull(Fn fn) { return this.andIsNotNull(Reflections.fnToFieldName(fn)); } public WeekendSqls andEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "=", "and")); return this; } public WeekendSqls andEqualTo(Fn fn, Object value) { return this.andEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls andNotEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "<>", "and")); return this; } public WeekendSqls andNotEqualTo(Fn fn, Object value) { return this.andNotEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls andGreaterThan(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, ">", "and")); return this; } public WeekendSqls andGreaterThan(Fn fn, Object value) { return this.andGreaterThan(Reflections.fnToFieldName(fn), value); } public WeekendSqls andGreaterThanOrEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, ">=", "and")); return this; } public WeekendSqls andGreaterThanOrEqualTo(Fn fn, Object value) { return this.andGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls andLessThan(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "<", "and")); return this; } public WeekendSqls andLessThan(Fn fn, Object value) { return this.andLessThan(Reflections.fnToFieldName(fn), value); } public WeekendSqls andLessThanOrEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "<=", "and")); return this; } public WeekendSqls andLessThanOrEqualTo(Fn fn, Object value) { return this.andLessThanOrEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls andIn(String property, Iterable values) { this.criteria.getCriterions().add(new Criterion(property, values, "in", "and")); return this; } public WeekendSqls andIn(Fn fn, Iterable values) { return this.andIn(Reflections.fnToFieldName(fn), values); } public WeekendSqls andNotIn(String property, Iterable values) { this.criteria.getCriterions().add(new Criterion(property, values, "not in", "and")); return this; } public WeekendSqls andNotIn(Fn fn, Iterable values) { return this.andNotIn(Reflections.fnToFieldName(fn), values); } public WeekendSqls andBetween(String property, Object value1, Object value2) { this.criteria.getCriterions().add(new Criterion(property, value1, value2, "between", "and")); return this; } public WeekendSqls andBetween(Fn fn, Object value1, Object value2) { return this.andBetween(Reflections.fnToFieldName(fn), value1, value2); } public WeekendSqls andNotBetween(String property, Object value1, Object value2) { this.criteria.getCriterions().add(new Criterion(property, value1, value2, "not between", "and")); return this; } public WeekendSqls andNotBetween(Fn fn, Object value1, Object value2) { return this.andNotBetween(Reflections.fnToFieldName(fn), value1, value2); } public WeekendSqls andLike(String property, String value) { this.criteria.getCriterions().add(new Criterion(property, value, "like", "and")); return this; } public WeekendSqls andLike(Fn fn, String value) { return this.andLike(Reflections.fnToFieldName(fn), value); } public WeekendSqls andNotLike(String property, String value) { this.criteria.getCriterions().add(new Criterion(property, value, "not like", "and")); return this; } public WeekendSqls andNotLike(Fn fn, String value) { return this.andNotLike(Reflections.fnToFieldName(fn), value); } public WeekendSqls orIsNull(String property) { this.criteria.getCriterions().add(new Criterion(property, "is null", "or")); return this; } public WeekendSqls orIsNull(Fn fn) { return this.orIsNull(Reflections.fnToFieldName(fn)); } public WeekendSqls orIsNotNull(String property) { this.criteria.getCriterions().add(new Criterion(property, "is not null", "or")); return this; } public WeekendSqls orIsNotNull(Fn fn) { return this.orIsNotNull(Reflections.fnToFieldName(fn)); } public WeekendSqls orEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "=", "or")); return this; } public WeekendSqls orEqualTo(Fn fn, Object value) { return this.orEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls orNotEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "<>", "or")); return this; } public WeekendSqls orNotEqualTo(Fn fn, Object value) { return this.orNotEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls orGreaterThan(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, ">", "or")); return this; } public WeekendSqls orGreaterThan(Fn fn, Object value) { return this.orGreaterThan(Reflections.fnToFieldName(fn), value); } public WeekendSqls orGreaterThanOrEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, ">=", "or")); return this; } public WeekendSqls orGreaterThanOrEqualTo(Fn fn, Object value) { return this.orGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls orLessThan(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "<", "or")); return this; } public WeekendSqls orLessThan(Fn fn, Object value) { return this.orLessThan(Reflections.fnToFieldName(fn), value); } public WeekendSqls orLessThanOrEqualTo(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "<=", "or")); return this; } public WeekendSqls orLessThanOrEqualTo(Fn fn, Object value) { return this.orLessThanOrEqualTo(Reflections.fnToFieldName(fn), value); } public WeekendSqls orIn(String property, Iterable values) { this.criteria.getCriterions().add(new Criterion(property, values, "in", "or")); return this; } public WeekendSqls orIn(Fn fn, Iterable values) { return this.orIn(Reflections.fnToFieldName(fn), values); } public WeekendSqls orNotIn(String property, Iterable values) { this.criteria.getCriterions().add(new Criterion(property, values, "not in", "or")); return this; } public WeekendSqls orNotIn(Fn fn, Iterable values) { return this.orNotIn(Reflections.fnToFieldName(fn), values); } public WeekendSqls orBetween(String property, Object value1, Object value2) { this.criteria.getCriterions().add(new Criterion(property, value1, value2, "between", "or")); return this; } public WeekendSqls orBetween(Fn fn, Object value1, Object value2) { return this.orBetween(Reflections.fnToFieldName(fn), value1, value2); } public WeekendSqls orNotBetween(String property, Object value1, Object value2) { this.criteria.getCriterions().add(new Criterion(property, value1, value2, "not between", "or")); return this; } public WeekendSqls orNotBetween(Fn fn, Object value1, Object value2) { return this.orNotBetween(Reflections.fnToFieldName(fn), value1, value2); } public WeekendSqls orLike(String property, String value) { this.criteria.getCriterions().add(new Criterion(property, value, "like", "or")); return this; } public WeekendSqls orLike(Fn fn, String value) { return this.orLike(Reflections.fnToFieldName(fn), value); } public WeekendSqls orNotLike(String property, Object value) { this.criteria.getCriterions().add(new Criterion(property, value, "not like", "or")); return this; } public WeekendSqls orNotLike(Fn fn, Object value) { return this.orNotLike(Reflections.fnToFieldName(fn), value); } @Override public Criteria getCriteria() { return criteria; } } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/WeekendSqlsUtils.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import tk.mybatis.mapper.weekend.reflection.Reflections; /** * {@link WeekendSqls} 的工具类,提供一系列静态方法,减少泛型参数的指定,使代码更简洁、清晰 * * 直接使用WeekSqls,以下的查询需要指定两次Country类: * List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) * .where(WeekendSqls.custom().andLike(Country::getCountryname, "%a%") * .andGreaterThan(Country::getCountrycode, "123")) * .build()); * * 使用 WeekendSqlsUtils,只需指定一次Country类: * List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) * .where(WeekendSqlsUtils.andLike(Country::getCountryname, "%a%") * .andGreaterThan(Country::getCountrycode, "123")) * .build()); * * 建议使用 import static,代码会简洁一些 * import static tk.mybatis.mapper.weekend.WeekendSqlsUtils.andLike; * * List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) * .where(andLike(Country::getCountryname, "%a%") * .andGreaterThan(Country::getCountrycode, "123")) * .build()); * @author linweichao * @date 2019/5/20 */ public class WeekendSqlsUtils { public static WeekendSqls andIsNull(String property) { return WeekendSqls.custom().andIsNull(property); } public static WeekendSqls andIsNull(Fn fn) { return WeekendSqls.custom().andIsNull(fn); } public static WeekendSqls andIsNotNull(String property) { return WeekendSqls.custom().andIsNotNull(property); } public static WeekendSqls andIsNotNull(Fn fn) { return WeekendSqls.custom().andIsNotNull(fn); } public static WeekendSqls andEqualTo(String property, Object value) { return WeekendSqls.custom().andEqualTo(property, value); } public static WeekendSqls andEqualTo(Fn fn, Object value) { return WeekendSqls.custom().andEqualTo(fn, value); } public static WeekendSqls andNotEqualTo(String property, Object value) { return WeekendSqls.custom().andNotEqualTo(property, value); } public static WeekendSqls andNotEqualTo(Fn fn, Object value) { return WeekendSqls.custom().andNotEqualTo(fn, value); } public static WeekendSqls andGreaterThan(String property, Object value) { return WeekendSqls.custom().andGreaterThan(property, value); } public static WeekendSqls andGreaterThan(Fn fn, Object value) { return WeekendSqls.custom().andGreaterThan(fn, value); } public static WeekendSqls andGreaterThanOrEqualTo(String property, Object value) { return WeekendSqls.custom().andGreaterThanOrEqualTo(property, value); } public static WeekendSqls andGreaterThanOrEqualTo(Fn fn, Object value) { return WeekendSqls.custom().andGreaterThanOrEqualTo(fn, value); } public static WeekendSqls andLessThan(String property, Object value) { return WeekendSqls.custom().andLessThan(property, value); } public static WeekendSqls andLessThan(Fn fn, Object value) { return WeekendSqls.custom().andLessThan(fn, value); } public static WeekendSqls andLessThanOrEqualTo(String property, Object value) { return WeekendSqls.custom().andLessThanOrEqualTo(property, value); } public static WeekendSqls andLessThanOrEqualTo(Fn fn, Object value) { return WeekendSqls.custom().andLessThanOrEqualTo(fn, value); } public static WeekendSqls andIn(String property, Iterable values) { return WeekendSqls.custom().andIn(property, values); } public static WeekendSqls andIn(Fn fn, Iterable values) { return WeekendSqls.custom().andIn(fn, values); } public static WeekendSqls andNotIn(String property, Iterable values) { return WeekendSqls.custom().andNotIn(property, values); } public static WeekendSqls andNotIn(Fn fn, Iterable values) { return WeekendSqls.custom().andNotIn(fn, values); } public static WeekendSqls andBetween(String property, Object value1, Object value2) { return WeekendSqls.custom().andBetween(property, value1, value2); } public static WeekendSqls andBetween(Fn fn, Object value1, Object value2) { return WeekendSqls.custom().andBetween(fn, value1, value2); } public static WeekendSqls andNotBetween(String property, Object value1, Object value2) { return WeekendSqls.custom().andNotBetween(property, value1, value2); } public static WeekendSqls andNotBetween(Fn fn, Object value1, Object value2) { return WeekendSqls.custom().andNotBetween(fn, value1, value2); } public static WeekendSqls andLike(String property, String value) { return WeekendSqls.custom().andLike(property, value); } public static WeekendSqls andLike(Fn fn, String value) { return WeekendSqls.custom().andLike(fn, value); } public static WeekendSqls andNotLike(String property, String value) { return WeekendSqls.custom().andNotLike(property, value); } public static WeekendSqls andNotLike(Fn fn, String value) { return WeekendSqls.custom().andNotLike(fn ,value); } public static WeekendSqls orIsNull(String property) { return WeekendSqls.custom().orIsNull(property); } public static WeekendSqls orIsNull(Fn fn) { return WeekendSqls.custom().orIsNull(fn); } public static WeekendSqls orIsNotNull(String property) { return WeekendSqls.custom().orIsNotNull(property); } public static WeekendSqls orIsNotNull(Fn fn) { return WeekendSqls.custom().orIsNotNull(fn); } public static WeekendSqls orEqualTo(String property, Object value) { return WeekendSqls.custom().orEqualTo(property, value); } public static WeekendSqls orEqualTo(Fn fn, String value) { return WeekendSqls.custom().orEqualTo(fn, value); } public static WeekendSqls orNotEqualTo(String property, Object value) { return WeekendSqls.custom().orNotEqualTo(property, value); } public static WeekendSqls orNotEqualTo(Fn fn, String value) { return WeekendSqls.custom().orNotEqualTo(fn, value); } public static WeekendSqls orGreaterThan(String property, Object value) { return WeekendSqls.custom().orGreaterThan(property, value); } public static WeekendSqls orGreaterThan(Fn fn, String value) { return WeekendSqls.custom().orGreaterThan(fn, value); } public static WeekendSqls orGreaterThanOrEqualTo(String property, Object value) { return WeekendSqls.custom().orGreaterThanOrEqualTo(property, value); } public static WeekendSqls orGreaterThanOrEqualTo(Fn fn, String value) { return WeekendSqls.custom().orGreaterThanOrEqualTo(fn, value); } public static WeekendSqls orLessThan(String property, Object value) { return WeekendSqls.custom().orLessThan(property, value); } public static WeekendSqls orLessThan(Fn fn, String value) { return WeekendSqls.custom().orLessThan(fn, value); } public static WeekendSqls orLessThanOrEqualTo(String property, Object value) { return WeekendSqls.custom().orLessThanOrEqualTo(property, value); } public static WeekendSqls orLessThanOrEqualTo(Fn fn, String value) { return WeekendSqls.custom().orLessThanOrEqualTo(fn, value); } public static WeekendSqls orIn(String property, Iterable values) { return WeekendSqls.custom().orIn(property, values); } public static WeekendSqls orIn(Fn fn, Iterable values) { return WeekendSqls.custom().orIn(fn, values); } public static WeekendSqls orNotIn(String property, Iterable values) { return WeekendSqls.custom().orNotIn(property, values); } public static WeekendSqls orNotIn(Fn fn, Iterable values) { return WeekendSqls.custom().orNotIn(fn, values); } public static WeekendSqls orBetween(String property, Object value1, Object value2) { return WeekendSqls.custom().orBetween(property, value1, value2); } public static WeekendSqls orBetween(Fn fn, Object value1, Object value2) { return WeekendSqls.custom().orBetween(fn, value1, value2); } public static WeekendSqls orNotBetween(String property, Object value1, Object value2) { return WeekendSqls.custom().orNotBetween(property, value1, value2); } public static WeekendSqls orNotBetween(Fn fn, Object value1, Object value2) { return WeekendSqls.custom().orNotBetween(fn, value1, value2); } public static WeekendSqls orLike(String property, String value) { return WeekendSqls.custom().orLike(property, value); } public static WeekendSqls orLike(Fn fn, String value) { return WeekendSqls.custom().orLike(fn, value); } public static WeekendSqls orNotLike(String property, String value) { return WeekendSqls.custom().orNotLike(property, value); } public static WeekendSqls orNotLike(Fn fn, String value) { return WeekendSqls.custom().orNotLike(fn, value); } public static String[] select(Fn... fn) { return Reflections.fnToFieldNames(fn); } } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/reflection/ReflectionOperationException.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend.reflection; /** * @author Frank */ public class ReflectionOperationException extends RuntimeException { public ReflectionOperationException() { } public ReflectionOperationException(String message) { super(message); } public ReflectionOperationException(String message, Throwable cause) { super(message, cause); } public ReflectionOperationException(Throwable cause) { super(cause); } public ReflectionOperationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } } ================================================ FILE: weekend/src/main/java/tk/mybatis/mapper/weekend/reflection/Reflections.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend.reflection; import tk.mybatis.mapper.weekend.Fn; import java.beans.Introspector; import java.lang.invoke.SerializedLambda; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; /** * @author Frank */ public class Reflections { private static final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*"); private static final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*"); private Reflections() { } public static String fnToFieldName(Fn fn) { try { Method method = fn.getClass().getDeclaredMethod("writeReplace"); method.setAccessible(Boolean.TRUE); SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn); String getter = serializedLambda.getImplMethodName(); if (GET_PATTERN.matcher(getter).matches()) { getter = getter.substring(3); } else if (IS_PATTERN.matcher(getter).matches()) { getter = getter.substring(2); } return Introspector.decapitalize(getter); } catch (ReflectiveOperationException e) { throw new ReflectionOperationException(e); } } public static String[] fnToFieldNames(Fn... fns) { List list = new ArrayList<>(); for (Fn fn : fns) { list.add(fnToFieldName(fn)); } return list.toArray(new String[0]); } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/MybatisHelper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import tk.mybatis.mapper.common.IdsMapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.MySqlMapper; import tk.mybatis.mapper.common.SqlServerMapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.io.IOException; import java.io.Reader; import java.sql.Connection; /** * Description: MybatisHelper * Author: liuzh * Update: liuzh(2014-06-06 13:33) */ public class MybatisHelper { private static SqlSessionFactory sqlSessionFactory; static { try { //创建SqlSessionFactory Reader reader = Resources.getResourceAsReader("mybatis-java.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); reader.close(); //创建数据库 SqlSession session = null; try { session = sqlSessionFactory.openSession(); //创建一个MapperHelper MapperHelper mapperHelper = new MapperHelper(); //特殊配置 Config config = new Config(); // 设置UUID生成策略 // 配置UUID生成策略需要使用OGNL表达式 // 默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "") //config.setUUID(""); // 主键自增回写方法,默认值MYSQL,详细说明请看文档 config.setIDENTITY("HSQLDB"); // 支持方法上的注解 // 3.3.1版本增加 config.setEnableMethodAnnotation(true); config.setNotEmpty(true); //校验Example中的类型是否一致 config.setCheckExampleEntityClass(true); //启用简单类型 config.setUseSimpleType(true); // 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle // 可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName, PropertyName //config.setSeqFormat("NEXT VALUE FOR {0}"); // 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename //config.setCatalog(""); // 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename // 如果同时设置了catalog,优先使用catalog.tablename //config.setSchema(""); // 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER) //config.setOrder("AFTER"); //设置配置 mapperHelper.setConfig(config); // 注册通用Mapper接口 - 可以自动注册继承的接口 mapperHelper.registerMapper(Mapper.class); mapperHelper.registerMapper(MySqlMapper.class); mapperHelper.registerMapper(SqlServerMapper.class); mapperHelper.registerMapper(IdsMapper.class); //配置完成后,执行下面的操作 mapperHelper.processConfiguration(session.getConfiguration()); //OK - mapperHelper的任务已经完成,可以不管了 Connection conn = session.getConnection(); reader = Resources.getResourceAsReader("CreateDB.sql"); ScriptRunner runner = new ScriptRunner(conn); runner.setLogWriter(null); runner.runScript(reader); reader.close(); } finally { if (session != null) { session.close(); } } } catch (IOException e) { e.printStackTrace(); } } /** * 获取Session * * @return */ public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/SqlCriteriaHelperTest.java ================================================ package tk.mybatis.mapper.weekend; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.weekend.entity.Country; import tk.mybatis.mapper.weekend.mapper.CountryMapper; import java.util.ArrayList; import java.util.List; /** * @author Cheng.Wei */ public class SqlCriteriaHelperTest { /** * 忽略null值问题 */ @Test public void ignore() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectBySqlCriteriaHelper = mapper.selectByExample(new Example.Builder(Country.class) .where(SqlCriteriaHelper.custom(Country.class) .andEqualTo(Country::getCountryname, null) .andLike(Country::getCountryname, "China")).build()); Assert.assertNotNull(selectBySqlCriteriaHelper); Assert.assertEquals(1, selectBySqlCriteriaHelper.size()); /* 不支持忽略 null List selectByWeekendSqls = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom() .andEqualTo(Country::getCountryname, null) .andLike(Country::getCountrycode, "China")).build()); */ } finally { sqlSession.close(); } } /** * 不忽略null属性 * 当属性为null 且不忽略 则转换查询 equal null 转 is null */ @Test public void required() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectBySqlCriteriaHelper = mapper.selectByExample(new Example.Builder(Country.class) .where(SqlCriteriaHelper.custom(Country.class) // required = true 则继续查询 .andEqualTo(Country::getCountryname, null, true)).build()); Assert.assertEquals(0, selectBySqlCriteriaHelper.size()); /*List selectByWeekendSqls = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom() .andEqualTo(Country::getCountryname, null)).build());*/ } finally { sqlSession.close(); } } /** * like查询 自动拼接 % */ @Test public void like() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectBySqlCriteriaHelper = mapper.selectByExample(new Example.Builder(Country.class) .where(SqlCriteriaHelper.custom(Country.class) .andLike(Country::getCountryname, "Chin") .orLike(Country::getCountryname, "A")).build()); Assert.assertEquals(18, selectBySqlCriteriaHelper.size()); /* 不支持自动带 % List selectByWeekendSqls = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom() .andLike(Country::getCountryname, "Chin") .orLike(Country::getCountryname, "A")).build()); //判断两个结果数组内容是否相同 Assert.assertArrayEquals(selectBySqlCriteriaHelper.toArray(), selectByWeekendSqls.toArray());*/ } finally { sqlSession.close(); } } /** * in查询 空集合问题 */ @Test public void list() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectBySqlCriteriaHelper = mapper.selectByExample(new Example.Builder(Country.class) .where(SqlCriteriaHelper.custom(Country.class) .andIn(Country::getCountryname, new ArrayList()) .orLike(Country::getCountryname, "A")).build()); Assert.assertNotNull(selectBySqlCriteriaHelper); Assert.assertEquals(17, selectBySqlCriteriaHelper.size()); //WeekendSqls 不支持空集合 /* List selectByWeekendSqls = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom() .andIn(Country::getCountryname, new ArrayList()) .orLike(Country::getCountryname, "A")).build()); */ //判断两个结果数组内容是否相同 //Assert.assertArrayEquals(selectBySqlCriteriaHelper.toArray(), selectByWeekendSqls.toArray()); } finally { sqlSession.close(); } } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/UserMapperTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.mapper.weekend.entity.Country; import tk.mybatis.mapper.weekend.entity.User; import tk.mybatis.mapper.weekend.mapper.CountryMapper; import tk.mybatis.mapper.weekend.mapper.UserMapper; import java.util.Arrays; import java.util.List; /** * @author Frank */ public class UserMapperTest { /** * 执行,然后看日志打出来的SQL */ @Test public void testSelectIdIsNull() { SqlSession sqlSession = MybatisHelper.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Weekend weekend = Weekend.of(User.class); weekend.weekendCriteria() .andIsNull(User::getId) .andBetween(User::getId, 0, 10) .andIn(User::getUserName, Arrays.asList("a", "b", "c")); List users = userMapper.selectByExample(weekend); for (User user : users) { System.out.println(user.getUserName()); } } @Test public void testExcludeAndSelectProperties() { SqlSession sqlSession = MybatisHelper.getSqlSession(); CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class); Weekend weekend1 = Weekend.of(Country.class); weekend1.excludeProperties(Country::getId, Country::getCountryname); //查看日志执行的sql countryMapper.selectByExample(weekend1); Weekend weekend2 = Weekend.of(Country.class); weekend2.selectProperties(Country::getId); //查看日志执行的sql countryMapper.selectByExample(weekend2); //count 查询 weekend2.withCountProperty(Country::getCountryname); countryMapper.selectCountByExample(weekend2); } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/WeekendSqlsTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.util.Sqls; import tk.mybatis.mapper.weekend.entity.Country; import tk.mybatis.mapper.weekend.mapper.CountryMapper; import java.util.List; /** * 测试WeekendSql构建者模式类 * * @author XuYin */ public class WeekendSqlsTest { @Test public void testWeekend() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom().andLike(Country::getCountryname, "China")).build()); List selectByExample = mapper.selectByExample( new Example.Builder(Country.class).where(Sqls.custom().andLike("countryname", "China")).build()); //判断两个结果数组内容是否相同 Assert.assertArrayEquals(selectByExample.toArray(), selectByWeekendSql.toArray()); } finally { sqlSession.close(); } } @Test public void testWeekendComplex() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) .where(WeekendSqls.custom().andLike(Country::getCountryname, "%a%") .andGreaterThan(Country::getCountrycode, "123")) .build()); List selectByExample = mapper.selectByExample(new Example.Builder(Country.class) .where(Sqls.custom().andLike("countryname", "%a%").andGreaterThan("countrycode", "123")).build()); // 判断两个结果数组内容是否相同 Assert.assertArrayEquals(selectByExample.toArray(), selectByWeekendSql.toArray()); } finally { sqlSession.close(); } } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/WeekendSqlsUtilsTest.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.util.Sqls; import tk.mybatis.mapper.weekend.entity.Country; import tk.mybatis.mapper.weekend.mapper.CountryMapper; import java.util.List; import static tk.mybatis.mapper.weekend.WeekendSqlsUtils.andLike; /** * @author linweichao * @date 2019/5/20 */ public class WeekendSqlsUtilsTest { @Test public void testWeekend() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) .where(andLike(Country::getCountryname, "China")).build()); List selectByExample = mapper.selectByExample( new Example.Builder(Country.class).where(Sqls.custom().andLike("countryname", "China")).build()); //判断两个结果数组内容是否相同 Assert.assertArrayEquals(selectByExample.toArray(), selectByWeekendSql.toArray()); } finally { sqlSession.close(); } } @Test public void testWeekendComplex() { SqlSession sqlSession = MybatisHelper.getSqlSession(); try { CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); List selectByWeekendSql = mapper.selectByExample(new Example.Builder(Country.class) .where(andLike(Country::getCountryname, "%a%") .andGreaterThan(Country::getCountrycode, "123")) .build()); List selectByExample = mapper.selectByExample(new Example.Builder(Country.class) .where(Sqls.custom().andLike("countryname", "%a%").andGreaterThan("countrycode", "123")).build()); // 判断两个结果数组内容是否相同 Assert.assertArrayEquals(selectByExample.toArray(), selectByWeekendSql.toArray()); } finally { sqlSession.close(); } } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/entity/Country.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend.entity; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; @Table() public class Country implements Serializable { private static final long serialVersionUID = 1L; @Id private Integer id; private String countryname; private String countrycode; public String getCountrycode() { return countrycode; } public void setCountrycode(String countrycode) { this.countrycode = countrycode; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/entity/User.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend.entity; import jakarta.persistence.Table; /** * @author Frank */ @Table(name = "user") public class User { private Long id; private String userName; public Long getId() { return id; } public User setId(Long id) { this.id = id; return this; } public String getUserName() { return userName; } public User setUserName(String userName) { this.userName = userName; return this; } } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/mapper/CountryMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.weekend.entity.Country; /** * @author liuzh */ public interface CountryMapper extends Mapper { } ================================================ FILE: weekend/src/test/java/tk/mybatis/mapper/weekend/mapper/UserMapper.java ================================================ /* * The MIT License (MIT) * * Copyright (c) 2014-2017 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package tk.mybatis.mapper.weekend.mapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.weekend.entity.User; /** * @author Frank */ public interface UserMapper extends Mapper { } ================================================ FILE: weekend/src/test/resources/CreateDB.sql ================================================ drop table user if exists; CREATE table user ( id int not null, user_name varchar(100) not null ); CREATE TABLE country ( id INTEGER NOT NULL PRIMARY KEY, countryname VARCHAR(32), countrycode VARCHAR(2) DEFAULT 'HH', version INTEGER DEFAULT 1 NOT NULL ); INSERT INTO country (id, countryname, countrycode, version) VALUES (1, 'Angola', 'AO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (2, 'Afghanistan', 'AF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (3, 'Albania', 'AL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (4, 'Algeria', 'DZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (5, 'Andorra', 'AD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (6, 'Anguilla', 'AI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (7, 'Antigua and Barbuda', 'AG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (8, 'Argentina', 'AR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (9, 'Armenia', 'AM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (10, 'Australia', 'AU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (11, 'Austria', 'AT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (12, 'Azerbaijan', 'AZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (13, 'Bahamas', 'BS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (14, 'Bahrain', 'BH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (15, 'Bangladesh', 'BD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (16, 'Barbados', 'BB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (17, 'Belarus', 'BY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (18, 'Belgium', 'BE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (19, 'Belize', 'BZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (20, 'Benin', 'BJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (21, 'Bermuda Is.', 'BM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (22, 'Bolivia', 'BO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (23, 'Botswana', 'BW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (24, 'Brazil', 'BR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (25, 'Brunei', 'BN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (26, 'Bulgaria', 'BG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (27, 'Burkina-faso', 'BF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (28, 'Burma', 'MM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (29, 'Burundi', 'BI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (30, 'Cameroon', 'CM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (31, 'Canada', 'CA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (32, 'Central African Republic', 'CF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (33, 'Chad', 'TD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (34, 'Chile', 'CL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (35, 'China', 'CN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (36, 'Colombia', 'CO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (37, 'Congo', 'CG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (38, 'Cook Is.', 'CK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (39, 'Costa Rica', 'CR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (40, 'Cuba', 'CU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (41, 'Cyprus', 'CY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (42, 'Czech Republic', 'CZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (43, 'Denmark', 'DK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (44, 'Djibouti', 'DJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (45, 'Dominica Rep.', 'DO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (46, 'Ecuador', 'EC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (47, 'Egypt', 'EG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (48, 'EI Salvador', 'SV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (49, 'Estonia', 'EE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (50, 'Ethiopia', 'ET', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (51, 'Fiji', 'FJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (52, 'Finland', 'FI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (53, 'France', 'FR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (54, 'French Guiana', 'GF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (55, 'Gabon', 'GA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (56, 'Gambia', 'GM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (57, 'Georgia', 'GE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (58, 'Germany', 'DE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (59, 'Ghana', 'GH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (60, 'Gibraltar', 'GI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (61, 'Greece', 'GR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (62, 'Grenada', 'GD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (63, 'Guam', 'GU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (64, 'Guatemala', 'GT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (65, 'Guinea', 'GN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (66, 'Guyana', 'GY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (67, 'Haiti', 'HT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (68, 'Honduras', 'HN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (69, 'Hongkong', 'HK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (70, 'Hungary', 'HU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (71, 'Iceland', 'IS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (72, 'India', 'IN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (73, 'Indonesia', 'ID', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (74, 'Iran', 'IR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (75, 'Iraq', 'IQ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (76, 'Ireland', 'IE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (77, 'Israel', 'IL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (78, 'Italy', 'IT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (79, 'Jamaica', 'JM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (80, 'Japan', 'JP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (81, 'Jordan', 'JO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (82, 'Kampuchea (Cambodia )', 'KH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (83, 'Kazakstan', 'KZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (84, 'Kenya', 'KE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (85, 'Korea', 'KR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (86, 'Kuwait', 'KW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (87, 'Kyrgyzstan', 'KG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (88, 'Laos', 'LA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (89, 'Latvia', 'LV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (90, 'Lebanon', 'LB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (91, 'Lesotho', 'LS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (92, 'Liberia', 'LR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (93, 'Libya', 'LY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (94, 'Liechtenstein', 'LI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (95, 'Lithuania', 'LT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (96, 'Luxembourg', 'LU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (97, 'Macao', 'MO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (98, 'Madagascar', 'MG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (99, 'Malawi', 'MW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (100, 'Malaysia', 'MY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (101, 'Maldives', 'MV', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (102, 'Mali', 'ML', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (103, 'Malta', 'MT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (104, 'Mauritius', 'MU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (105, 'Mexico', 'MX', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (106, 'Moldova, Republic of', 'MD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (107, 'Monaco', 'MC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (108, 'Mongolia', 'MN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (109, 'Montserrat Is', 'MS', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (110, 'Morocco', 'MA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (111, 'Mozambique', 'MZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (112, 'Namibia', 'NA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (113, 'Nauru', 'NR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (114, 'Nepal', 'NP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (115, 'Netherlands', 'NL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (116, 'New Zealand', 'NZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (117, 'Nicaragua', 'NI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (118, 'Niger', 'NE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (119, 'Nigeria', 'NG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (120, 'North Korea', 'KP', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (121, 'Norway', 'NO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (122, 'Oman', 'OM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (123, 'Pakistan', 'PK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (124, 'Panama', 'PA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (125, 'Papua New Cuinea', 'PG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (126, 'Paraguay', 'PY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (127, 'Peru', 'PE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (128, 'Philippines', 'PH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (129, 'Poland', 'PL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (130, 'French Polynesia', 'PF', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (131, 'Portugal', 'PT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (132, 'Puerto Rico', 'PR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (133, 'Qatar', 'QA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (134, 'Romania', 'RO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (135, 'Russia', 'RU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (136, 'Saint Lueia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (137, 'Saint Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (138, 'San Marino', 'SM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (139, 'Sao Tome and Principe', 'ST', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (140, 'Saudi Arabia', 'SA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (141, 'Senegal', 'SN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (142, 'Seychelles', 'SC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (143, 'Sierra Leone', 'SL', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (144, 'Singapore', 'SG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (145, 'Slovakia', 'SK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (146, 'Slovenia', 'SI', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (147, 'Solomon Is', 'SB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (148, 'Somali', 'SO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (149, 'South Africa', 'ZA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (150, 'Spain', 'ES', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (151, 'Sri Lanka', 'LK', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (152, 'St.Lucia', 'LC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (153, 'St.Vincent', 'VC', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (154, 'Sudan', 'SD', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (155, 'Suriname', 'SR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (156, 'Swaziland', 'SZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (157, 'Sweden', 'SE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (158, 'Switzerland', 'CH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (159, 'Syria', 'SY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (160, 'Taiwan', 'TW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (161, 'Tajikstan', 'TJ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (162, 'Tanzania', 'TZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (163, 'Thailand', 'TH', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (164, 'Togo', 'TG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (165, 'Tonga', 'TO', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (166, 'Trinidad and Tobago', 'TT', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (167, 'Tunisia', 'TN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (168, 'Turkey', 'TR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (169, 'Turkmenistan', 'TM', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (170, 'Uganda', 'UG', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (171, 'Ukraine', 'UA', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (172, 'United Arab Emirates', 'AE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (173, 'United Kiongdom', 'GB', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (174, 'United States of America', 'US', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (175, 'Uruguay', 'UY', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (176, 'Uzbekistan', 'UZ', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (177, 'Venezuela', 'VE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (178, 'Vietnam', 'VN', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (179, 'Yemen', 'YE', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (180, 'Yugoslavia', 'YU', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (181, 'Zimbabwe', 'ZW', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (182, 'Zaire', 'ZR', 1); INSERT INTO country (id, countryname, countrycode, version) VALUES (183, 'Zambia', 'ZM', 1); ================================================ FILE: weekend/src/test/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: weekend/src/test/resources/mybatis-java.xml ================================================