可能有些人也有过类似需求,一般都会选择使用其他的方式如spring-jdbc等方式解决。
能否通过mybatis实现这样的功能呢?
为了让通用mapper更彻底的支持多表操作以及更灵活的操作,在2.2.0版本增加了一个可以直接执行sql的新类sqlmapper。
我们来了解一下sqlmapper。
sqlmapper提供的方法
sqlmapper提供了以下这些公共方法:
- map<string,object> selectone(string sql)
- map<string,object> selectone(string sql, object value)
- <t> t selectone(string sql, class<t> resulttype)
- <t> t selectone(string sql, object value, class<t> resulttype)
- list<map<string,object>> selectlist(string sql)
- list<map<string,object>> selectlist(string sql, object value)
- <t> list<t> selectlist(string sql, class<t> resulttype)
- <t> list<t> selectlist(string sql, object value, class<t> resulttype)
- int insert(string sql)
- int insert(string sql, object value)
- int update(string sql)
- int update(string sql, object value)
- int delete(string sql)
- int delete(string sql, object value)
一共14个方法,这些方法的命名和参数和sqlsession接口的很像,只是基本上第一个参数都成了sql。
其中object value为入参,入参形式和sqlsession中的入参一样,带有入参的方法,在使用时sql可以包含#{param}或${param}形式的参数,这些参数需要通过入参来传值。需要的参数过多的时候,参数可以使用map类型。另外这种情况下的sql还支持下面这种复杂形式:
| 
								1
 
								2
						 | string sql = "<script>select * from sys_user where 1=1"+ "<if test=\\"usertype != null\\">usertype = #{usertype}</if></script>"; | 
这种情况用的比较少,不多说。
不带有object value的所有方法,sql中如果有参数需要手动拼接成一个可以直接执行的sql语句。
在selectxxx方法中,使用class<t> resulttype可以指定返回类型,否则就是map<string,object>类型。
实例化sqlmapper
sqlmapper构造参数public sqlmapper(sqlsession sqlsession),需要一个入参sqlsession sqlsession,在一般系统中,可以按照下面的方式获取:
| 
								1
 
								2
 
								3
						 | sqlsession sqlsession = (...);//通过某些方法获取sqlsession//创建sqlmappersqlmapper sqlmapper = newsqlmapper(sqlsession); | 
如果使用的spring,那么可以按照下面的方式配置<bean>:
| 
								1
 
								2
 
								3
						 | <bean id="sqlmapper"class="com.github.abel533.sql.sqlmapper"scope="prototype"><constructor-arg ref="sqlsession"/></bean> | 
在service中使用的时候可以直接使用@autowired注入。
简单例子
在src/test/java目录的com.github.abel533.sql包中包含这些方法的测试。
下面挑几个看看如何使用。
selectlist
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
						 | //查询,返回list<map>list<map<string, object>> list = sqlmapper.selectlist("select * from country where id < 11");//查询,返回指定的实体类list<country> countrylist = sqlmapper.selectlist("select * from country where id < 11", country.class);//查询,带参数countrylist = sqlmapper.selectlist("select * from country where id < #{id}", 11, country.class);//复杂点的查询,这里参数和上面不同的地方,在于传入了一个对象country country = newcountry();country.setid(11);countrylist = sqlmapper.selectlist("<script>"+"select * from country "+" <where>"+" <if test=\\"id != null\\">"+" id < #{id}"+" </if>"+" </where>"+"</script>", country, country.class); | 
selectone
| 
								1
 
								2
 
								3
 
								4
						 | map<string, object> map = sqlmapper.selectone("select * from country where id = 35");map = sqlmapper.selectone("select * from country where id = #{id}", 35);country country = sqlmapper.selectone("select * from country where id = 35", country.class);country = sqlmapper.selectone("select * from country where id = #{id}", 35, country.class); | 
insert,update,delete
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
 
								18
 
								19
						 | //insertintresult = sqlmapper.insert("insert into country values(1921,'天朝','tc')");country tc = newcountry();tc.setid(1921);tc.setcountryname("天朝");tc.setcountrycode("tc");//注意这里的countrycode和countryname故意写反的result = sqlmapper.insert("insert into country values(#{id},#{countrycode},#{countryname})", tc);//updateresult = sqlmapper.update("update country set countryname = '天朝' where id = 35");tc = newcountry();tc.setid(35);tc.setcountryname("天朝");intresult = sqlmapper.update("update country set countryname = #{countryname}"+ " where id in(select id from country where countryname like 'a%')", tc);//deleteresult = sqlmapper.delete("delete from country where id = 35");result = sqlmapper.delete("delete from country where id = #{id}", 35); | 
注意
通过上面这些例子应该能对此有个基本的了解,但是如果你使用参数方式,建议阅读下面的文章:
深入了解mybatis参数
实现原理
最初想要设计这个功能的时候,感觉会很复杂,想的也复杂,需要很多个类,因此当时没有实现。
突发奇想,设计了现在的这种方式。并且有种强烈的感觉就是幸好昨天没有尝试去实现,因为昨天晚上思考这个问题的时候是晚上10点多,而今天晚上7点开始思考。我很庆幸在一个更清醒的状态下去写这段代码。
下面简单说思路和实现方式。
在写mybatis分页插件的时候熟悉了mappedstatement类。
在写通用mapper的时候熟悉了xml转sqlnode结构。
如果我根据sql动态的创建一个mappedstatement,然后使用mappedstatement的id在sqlsession中执行不就可以了吗?
想到这一点,一切就简单了。
看看下面select查询创建mappedstatement的代码:
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
 
								18
 
								19
 
								20
 
								21
						 | /*** 创建一个查询的ms* @param msid* @param sqlsource 执行的sqlsource* @param resulttype 返回的结果类型*/privatevoidnewselectmappedstatement(string msid, sqlsource sqlsource, finalclass<?> resulttype) {mappedstatement ms = newmappedstatement.builder(configuration, msid, sqlsource, sqlcommandtype.select).resultmaps(newarraylist<resultmap>() {{add(newresultmap.builder(configuration,"defaultresultmap",resulttype,newarraylist<resultmapping>(0)).build());}}).build();//缓存configuration.addmappedstatement(ms);} | 
代码是不是很简单,这段代码的关键是参数sqlsource,下面是创建sqlsource的方法,分为两种。
一种是一个完整的sql,不需要参数的,可以直接执行的:
| 
								1
						 | staticsqlsource sqlsource = newstaticsqlsource(configuration, sql); | 
其中configuration从sqlsession中获取,sql就是用户传入到sql语句,是不是也很简单?
另一种是支持动态sql的,支持参数的sqlsource:
| 
								1
						 | sqlsource sqlsource = languagedriver.createsqlsource(configuration, sql, parametertype); | 
是不是也很简单?这个方法其实可以兼容上面的staticsqlsource,这里比上面多了一个parametertype,因为这儿是可以传递参数的,另外languagedriver是从configuration中获取的。
是不是很简单?
我一开始也没想到mybatis直接执行sql实现起来会这么的容易。
insert,delete,update方法的创建更容易,因为他们的返回值都是int,所以处理起来更简单,有兴趣的可以查看sqlmapper的源码。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对快网idc的支持。如果你想了解更多相关内容请查看下面相关链接
原文链接:https://blog.csdn.net/isea533/article/details/44193939
相关文章
- 个人服务器网站搭建:如何选择合适的服务器提供商? 2025-06-10
- ASP.NET自助建站系统中如何实现多语言支持? 2025-06-10
- 64M VPS建站:如何选择最适合的网站建设平台? 2025-06-10
- ASP.NET本地开发时常见的配置错误及解决方法? 2025-06-10
- ASP.NET自助建站系统的数据库备份与恢复操作指南 2025-06-10
- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
- 
            2025-05-24 98
- 
            2025-05-29 36
- 
            2025-05-29 37
- 
            2025-05-29 94
- 
            2025-05-29 20
 
        
 
    		 
            	 
															 
         
         
        
 
                        