/mybatis-generalmapper

A middle-ware for mybatis plus, you can use it to CRUD single table without any sql.

Primary LanguageJavaApache License 2.0Apache-2.0

#Mybatis-generalmapper

  • A middle-ware for mybatis plus, you can use it to CRUD single table without any sql.
  • 一个基于mybatis-plus的中间件,让单表CURD无SQL

Build Status License

What you need is:

  • create an entity with annotation: @TableId(Required), @TableName(Optional, required if entityName not eq tableName, eg: No need:TblUser - tbl_user; Required: User - tbl_user) ,
  • then configure typeAliasesPackage to make the entity be scanned by mybatis(v_1.1 add support for com.github.yuxiaobin.*.persistent),
  • import GeneralMapper, invoke CRUD method with the entity.

你只需要做:

  • 创建创建实体带有@TableId(必须), @TableName(可以有,如果表名和实体类名不相同则需要,如果满足驼峰命名相同,可以不用)
  • 配置typeAliasesPackage 可以扫描到该实体(v_1.1支持通配符扫描实体,com.github.yuxiaobin.*.persistent)
  • 引入GeneralMapper, 就可以调用CRUD

##Mybatis-plus部分 具体使用,可参考github上wiki, 生成代码参考MybatisPlusGenerator.java

  • About plus: a middle-ware for mybatis, CRUD operation for single table, no need to configure mapper.xml, SQL will auto be injected.
  • Mybatis-generalmapper uses the sql injection by plus(currently use plus v_1.5).

#Maven

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus</artifactId>
	<version>1.5</version>
</dependency>
<dependency>
	<groupId>com.github.yuxiaobin</groupId>
	<artifactId>mybatis-generalmapper</artifactId>
	<version>1.8.2</version>
</dependency>

#Release History

  • v_1.0: init
  • v_1.1: Add support typeAliasesPackage contains : com.github.yuxiaobin..persistent
  • v_1.2: Add support typeAliasesPackage contains ;,\t\n: com.github.yuxiaobin.*.persistent;com.your.company.persistent
  • v_1.3: Add support typeAliasesPackage contains multiple : com.projecta..persistent;com.projectb..persistent;com.projectc..persistent
  • v_1.4: Add deleteByEW(EntityWrapper);
  • v_1.5: Wrap result : use ew.entity.type, to solve returned parent class object;
  • v_1.6: Add GeneralEntityWrapper: to solve such as ew.and("col_dt={0}", Date val) sqlSegment issue.
  • v_1.7: SQL inject bypass classes under java/apache/spring/hibernate; use GeneralEntityWrapper in byEW methods to avoid v_1.6 issue.
  • v_1.8: Add GeneralPaginationInterceptor,GeneralSqlChangeInterceptor, to allow multiple Sql change interceptors for Query ONLY(See Sample Code below).
  • v_1.8.1: Bug fixing.
  • v_1.8.2: Bug fixing for typeAliasesPackage contains only one package, which will leads to VO not scanned.
  • v_1.8.3: Bug fixing for insertBatch() updateBatch() method: setup jdbc type when init sessionFactoryBean.
  • v_1.8.4: Add oracle/mysql keywords properties support: define keywords.properties in classpath(refer to src/test/resources/keywords.properties).
  • v_1.8.5: Bug fixing for batchUpdatebyIds
  • v_1.8.6: Add Optimistic Lock Support.(refer to test\java...\test.OptLockerIntegerVersionTest)
  • v_1.8.7: Bug fixing for some cases that causes multiple typeAliasesPackage won't be registered. Refer to GeneralConfiguration.
  • v_1.8.7-beta: Adjust sql inject time earlier: move to GeneralSqlSessionFactoryBean.getObject(), to avoid some special cases(spring boot with some FactoryBean) which causes @PostConstruct not work properly.
  • v_1.8.8: Add query total count for pagination interceptor

#Roadmap

  • support entityWrapper can shield the column names.
  • User.java has public static class NAME = new class("column_name");
  • ew.and(User.NAME.eq("abc")) -> user_name='abc';

#Test Cases

  • Refer to junit test cases for spring xml based.

#Some Sample Code for Spring Boot

@Configuraion
public class GeneralMapperConfig {
	private final GeneralSqlChangeInterceptor[] interceptors;
	public GeneralMapperConfig(ObjectProvider<GeneralSqlChangeInterceptor[]> interceptorsProvider){
		this.interceptors = interceptorsProvider.getIfAvailable();
	}
	@Bean
	public GeneralPaginationInterceptor paginationInterceptor(){
		return new GeneralPaginationInterceptor(interceptors);
	}
}

@Configuration
@MapperScan("com.github.yuxiaobin.test.mapper")
@Import({GeneralMapperBootstrapConfiguration.class})
@EnableConfigurationProperties(MybatisProperties.class)
public class MybatisConfig{
	private final MybatisProperties properties;
	private final Interceptor[] interceptors;
	private final ResourceLoader resourceLoader;
	private final DatabaseIdProvider databaseIdProvider;
	public MybatisConfig(MybatisProperties properties,
							            ObjectProvider<Interceptor[]> interceptorsProvider,
							            ResourceLoader resourceLoader,
							            ObjectProvider<DatabaseIdProvider> databaseIdProvider){
		this.properties = properties;
		this.interceptors = interceptorsProvider.getIfAvailable();
		this.resourceLoader = resourceLoader;
		this.databaseIdProvider = databaseIdProvider.getIfAvailable();
}

@Bean
public GeneralMapper generalMapper(GeneralSqlSessionFactoryBean factoryBean) throws Exception{
	GeneralMapper generalMapper = new GeneralMapper();
	generalMapper.setSqlSessionFactory(factoryBean.getObject());
	return generalMapper;
}

@Bean
public GeneralSqlSessionFactoryBean sqlSessionFactory (DataSource dataSource){
	GeneralSqlSessionFactoryBean sqlSessionFactory = new GeneralSqlSessionFactoryBean();
	sqlSessionFactory.setDataSource(dataSource);
	sqlSessionFactory.setVfs(SpringBootVFS.class);
	if (!ObjectUtils.isEmpty(this.interceptors)) {
		sqlSessionFactory.setPlugins(this.interceptors);
	}else{
		sqlSessionFactory.setPlugins(new Interceptor[]{new GeneralPaginationInterceptor(null)});
	}
	if (this.databaseIdProvider != null) {
		sqlSessionFactory.setDatabaseIdProvider(this.databaseIdProvider);
	}
	if(!StringUtils.isEmpty(properties.getTypeAliasesPackage())){
		sqlSessionFactory.setTypeAliasesPackage(properties.getTypeAliasesPackage());//多个不同的包,可以用 , ; 分隔
	}else{
		sqlSessionFactory.setTypeAliasesPackage("com.github.yuxiaobin.test.persistent");
	}
	if(StringUtils.hasText(this.properties.getConfigLocation())) {
		 sqlSessionFactory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
	}
	GeneralConfiguration configuration = new GeneralConfiguration();
	configuration.setDefaultScriptingLanguage(GeneralMybatisXMLLanguageDriver.class);
	configuration.setJdbcTypeForNull(JdbcType.NULL);
	org.apache.ibatis.session.Configuration config = properties.getConfiguration();
	if(config!=null){
		configuration.setMapUnderscoreToCamelCase(config.isMapUnderscoreToCamelCase());
	}
	sqlSessionFactory.setConfiguration(configuration);
	return sqlSessionFactory;
}

Service:
	@Autowired
	GeneralMapper generalMapper;//use spring framework
	
	SampleTO sample= new Sample();
	sample.setName("123");//add condition: sample_name='123'
	EntityWrapper<SampleTO> ew = new EntityWrapper<>(sample);
	ew.where("sample_age>{0}",18);// add condition: sample_age>18 //will support use property name in future
	ew.and(" sample_dt > {0} and sample_dt < {1} ", LocalDate.of(2015, 12, 12).toString(), LocalDate.of(2016, 1, 1).toString());
	ew.like("sample_nkname", "a");
	List<SampleTO> list =generalMapper.selectList(ew);
	List<SampleTO> list =generalMapper.selectPage(new Page<>(1,10),ew);
/**********SQL:*********/
//select * from tbl_sample where sample_name='123' and sample_age>18 and (sample_dt>'2015-12-12' and sample_dt<'2016-1-1') and sample_nkname like '%a%'