MyBatis直接执行SQL的工具SqlMapper
可能有些人也有过类似需求,一般都会选择使用其他的方式如Spring-JDBC等方式解决。
能否通过MyBatis实现这样的功能呢?
为了让通用Mapper更彻底的支持多表操作以及更灵活的操作,在2.2.0版本增加了一个可以直接执行SQL的新类SqlMapper。
我们来了解一下SqlMapper。
SqlMapper提供的方法
SqlMapper提供了以下这些公共方法:
- Map
selectOne(Stringsql) - Map
selectOne(Stringsql,Objectvalue) TselectOne(Stringsql,Class resultType) TselectOne(Stringsql,Objectvalue,Class resultType) - List
- List
List selectList(Stringsql,Class resultType) List selectList(Stringsql,Objectvalue,Class resultType) - intinsert(Stringsql)
- intinsert(Stringsql,Objectvalue)
- intupdate(Stringsql)
- intupdate(Stringsql,Objectvalue)
- intdelete(Stringsql)
- intdelete(Stringsql,Objectvalue)
一共14个方法,这些方法的命名和参数和SqlSession接口的很像,只是基本上第一个参数都成了sql。
其中Objectvalue为入参,入参形式和SqlSession中的入参一样,带有入参的方法,在使用时sql可以包含#{param}或${param}形式的参数,这些参数需要通过入参来传值。需要的参数过多的时候,参数可以使用Map类型。另外这种情况下的sql还支持下面这种复杂形式:
Stringsql="";
这种情况用的比较少,不多说。
不带有Objectvalue的所有方法,sql中如果有参数需要手动拼接成一个可以直接执行的sql语句。
在selectXXX方法中,使用Class
实例化SqlMapper
SqlMapper构造参数publicSqlMapper(SqlSessionsqlSession),需要一个入参SqlSessionsqlSession,在一般系统中,可以按照下面的方式获取:
SqlSessionsqlSession=(...);//通过某些方法获取sqlSession //创建sqlMapper SqlMappersqlMapper=newSqlMapper(sqlSession);
如果使用的Spring,那么可以按照下面的方式配置
在Service中使用的时候可以直接使用@Autowired注入。
简单例子
在src/test/java目录的com.github.abel533.sql包中包含这些方法的测试。
下面挑几个看看如何使用。
selectList
//查询,返回List
selectOne
Mapmap=sqlMapper.selectOne("select*fromcountrywhereid=35"); map=sqlMapper.selectOne("select*fromcountrywhereid=#{id}",35); Countrycountry=sqlMapper.selectOne("select*fromcountrywhereid=35",Country.class); country=sqlMapper.selectOne("select*fromcountrywhereid=#{id}",35,Country.class);
insert,update,delete
//insert intresult=sqlMapper.insert("insertintocountryvalues(1921,'天朝','TC')"); Countrytc=newCountry(); tc.setId(1921); tc.setCountryname("天朝"); tc.setCountrycode("TC"); //注意这里的countrycode和countryname故意写反的 result=sqlMapper.insert("insertintocountryvalues(#{id},#{countrycode},#{countryname})" ,tc); //update result=sqlMapper.update("updatecountrysetcountryname='天朝'whereid=35"); tc=newCountry(); tc.setId(35); tc.setCountryname("天朝"); intresult=sqlMapper.update("updatecountrysetcountryname=#{countryname}"+ "whereidin(selectidfromcountrywherecountrynamelike'A%')",tc); //delete result=sqlMapper.delete("deletefromcountrywhereid=35"); result=sqlMapper.delete("deletefromcountrywhereid=#{id}",35);
注意
通过上面这些例子应该能对此有个基本的了解,但是如果你使用参数方式,建议阅读下面的文章:
深入了解MyBatis参数
实现原理
最初想要设计这个功能的时候,感觉会很复杂,想的也复杂,需要很多个类,因此当时没有实现。
突发奇想,设计了现在的这种方式。并且有种强烈的感觉就是幸好昨天没有尝试去实现,因为昨天晚上思考这个问题的时候是晚上10点多,而今天晚上7点开始思考。我很庆幸在一个更清醒的状态下去写这段代码。
下面简单说思路和实现方式。
在写MyBatis分页插件的时候熟悉了MappedStatement类。
在写通用Mapper的时候熟悉了xml转SqlNode结构。
如果我根据SQL动态的创建一个MappedStatement,然后使用MappedStatement的id在sqlSession中执行不就可以了吗?
想到这一点,一切就简单了。
看看下面select查询创建MappedStatement的代码:
/** *创建一个查询的MS *@parammsId *@paramsqlSource执行的sqlSource *@paramresultType返回的结果类型 */ privatevoidnewSelectMappedStatement(StringmsId,SqlSourcesqlSource,finalClass>resultType){ MappedStatementms=newMappedStatement.Builder( configuration,msId,sqlSource,SqlCommandType.SELECT) .resultMaps(newArrayList(){ { add(newResultMap.Builder(configuration, "defaultResultMap", resultType, newArrayList (0)).build()); } }) .build(); //缓存 configuration.addMappedStatement(ms); }
代码是不是很简单,这段代码的关键是参数sqlSource,下面是创建SqlSource的方法,分为两种。
一种是一个完整的sql,不需要参数的,可以直接执行的:
StaticSqlSourcesqlSource=newStaticSqlSource(configuration,sql);
其中configuration从sqlSession中获取,sql就是用户传入到sql语句,是不是也很简单?
另一种是支持动态sql的,支持参数的SqlSource:
SqlSourcesqlSource=languageDriver.createSqlSource(configuration,sql,parameterType);
是不是也很简单?这个方法其实可以兼容上面的StaticSqlSource,这里比上面多了一个parameterType,因为这儿是可以传递参数的,另外languageDriver是从configuration中获取的。
是不是很简单?
我一开始也没想到MyBatis直接执行sql实现起来会这么的容易。
insert,delete,update方法的创建更容易,因为他们的返回值都是int,所以处理起来更简单,有兴趣的可以查看SqlMapper的源码。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。如果你想了解更多相关内容请查看下面相关链接
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。