好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

如何批量测试Mybatis项目中的Sql是否正确详解

去oracle行动

最近公司要发展海外项目,所以要将现有的系统全部平移过去,另外数据库也要从原来的oracle变为mysql。公司的数据库交互层面使用的是mybatis,而oracle与mysql也有一些语法上的不同。所以在项目中的sql要改动,但是多个项目中涉及到的sql非常多,如果仅凭人工一条一条辨别的话,工作量有点大。所以就萌发出了直接将数据源变为mysql,利用反射批量执行mapper中的方法,然后如果有参数的话,就设置为默认的初始值,然后记录下来成功的数据和失败的数据,这样就可以根据失败原因进行修改。

能够节省很大的时间。

执行效果

代码介绍

总体思路就三步

通过反射获得要执行的mapper类的所有方法 获得方法中的参数,并赋值 执行

?

1

2

autotestmapper autotestmapper = new autotestmapper( "存放mapper全路径名" );

autotestmapper.opensqlsession(sqlsessionfactory);

在构造函数中传入全路径名后,进行解析,解析出包名和所有的文件名并存储起来

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public autotestmapper(string path) throws ioexception, classnotfoundexception {

string mappercontent = getfilecontent(path);

string pathpattern = "import [a-z,a-z,/.]+;" ;

string[] patharr = matchmethod(pathpattern, mappercontent).split( ";" );

for ( int i = 0 ; i < patharr.length; i++) {

patharr[i] = patharr[i].replaceall( "import " , "" );

class cls = class .forname(patharr[i]);

if (!cls.isinterface()) {

type_array.add(cls);

}

}

//获得全路径名的前缀

string packpattern = "package [a-z,a-z,/.]+;" ;

string[] packpatharr = matchmethod(packpattern, mappercontent).split( ";" );

string packpath = packpatharr[ 0 ].replaceall( "package " , "" ).replaceall( ";" , "" );

this .pack_path = packpath;

}

然后调用opensqlsession的方法,传入sqlsessionfactory参数

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

list<map< class , object>> list = new arraylist<>();

list<string> invokesuccess = new arraylist<>();

list<string> invokefail = new arraylist<>();

for (string filename : file_name) {

class cls = class .forname(pack_path + "." + filename);

//添加mapper

if (!sqlsessionfactory.getconfiguration().hasmapper(cls)){

sqlsessionfactory.getconfiguration().addmapper(cls);

}

//获得mapper

object mapper = sqlsessionfactory.opensession().getmapper(cls);

//反射执行mapper的方法

map<string, list<string>> resultmap = autotestinvoke(cls, mapper);

invokesuccess.addall(resultmap.get(success_flg));

invokefail.addall(resultmap.get(fail_flg));

}

然后通过mybatyis提供的方法getmapper()传入类名获得所要mapper类。核心方法就是autotestinvoke()方法了

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

    private map<string, list<string>> autotestinvoke( class c, object o)

{

method[] declaredmethods = c.getdeclaredmethods();

string filename = c.getname().substring(c.getname().lastindexof( "." ));

list<string> invokesuccess = new arraylist<>();

list<string> invokefail = new arraylist<>();

map<string, list<string>> resultmap = new hashmap<>();

//给参数赋初始值

for (method method : declaredmethods) {

list<object> list = new arraylist<>();

for ( class cls : method.getparametertypes()) {

object par = new object();

if (type_array.contains(cls)) {

  if (cls.equals(string. class )) {

  par = "1" ;

  } else {

  try {

  par = cls.newinstance();

  assignment(cls, par);

  } catch (instantiationexception e) {

  if (cls.isprimitive()) {

  cls = primitiveclazz.get(cls.getname());

  }

  try {

  par = cls.getdeclaredconstructor(string. class ).newinstance( "1" );

 

  } catch (nosuchmethodexception e1){

  system.out.println(cls.getname()+e);

  }

  }

  }

} else if ( "java.util.map" .equals(cls.getname())){

  par = getmapdata(c.getname()+ "." +method.getname());

}

list.add(par);

}

try {

method.invoke(o, list.toarray());

invokesuccess.add( "success: " + filename + "." + method.getname());

} catch (exception e) {

invokefail.add( "error:" + method.getname() + " error info:" + e);

}

}

resultmap.put(success_flg, invokesuccess);

resultmap.put(fail_flg, invokefail);

return resultmap;

}

这里面完成为参数赋初始值,和执行的逻辑。

使用说明

导入jar包

maven

?

1

2

3

4

5

<dependency>

  <groupid>com.github.modouxiansheng</groupid>

  <artifactid>convenientutil</artifactid>

  <version> 1.3 -release</version>

</dependency>

gradle

?

1

compile 'com.github.modouxiansheng:convenientutil:1.1-release'

创建mybatis-config.xml文件

在项目的resource文件夹下创建mybatis-config.xml文件,里面内容如下,里面value值为想要测的数据库的连接信息

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<!doctype configuration

  public "-//mybatis.org//dtd config 3.0//en"

  "http://mybatis.org/dtd/mybatis-3-config.dtd" >

<configuration>

  <environments default = "dev" >

  <environment id= "dev" >

  <transactionmanager type= "jdbc" ></transactionmanager>

  <datasource type= "unpooled" >

  <property name= "driver" value= "" />

  <property name= "url" value= "" />

  <property name= "username" value= "" />

  <property name= "password" value= "" />

  </datasource>

  </environment>

  </environments>

</configuration>

在测试类中编写代码

在测试类中编写如下代码

?

1

2

3

4

5

reader resourceasreader = resources.getresourceasreader( "mybatis-config.xml" );

sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(resourceasreader);

resourceasreader.close();

autotestmapper autotestmapper = new autotestmapper( "想要测试的mapper文件夹全路径名" );

autotestmapper.opensqlsession(sqlsessionfactory);

查看输出的信息

然后会打印出执行成功的sql,执行失败的sql。如果失败的话会有原因。
success: tsessetmanualmapper.updateflgdelautointimepay
success: tsessetmanualmapper.getautosetmanualordlistcount
success: tsessetmanualmapper.updateautosetmanualord
success: tsessetmanualmapper.queryautosetmanualorddetail
success: tsessetmanualmapper.querysetmanualordlistcount
success: shortmessagemapper.querypayinssminfo
-------------------
|error: |tsessetmanualmapper.queryautosetmanualordlist| every derived table must have its own alias|
|error: |tsessetmanualmapper.querysetmanualordlist| every derived table must have its own alias|

这样就能够根据错误信息进行更改了。

github地址: https://github测试数据/modouxiansheng/convenientuti

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

原文链接:https://juejin.im/post/5c0108fdf265da613e21f997

查看更多关于如何批量测试Mybatis项目中的Sql是否正确详解的详细内容...

  阅读:19次