Пакетная проверка правильности Sql в проекте Mybatis

MyBatis

Перейти к действию оракула

В последнее время компания хочет развивать зарубежные проекты, поэтому все существующие системы нужно перенести в прошлое, а базу данных поменять с исходной.OracleстатьMysql. Уровень взаимодействия с базой данных компании используетMybatisOracleиMysqlЕсть также некоторые грамматические различия. Следовательно, Sql в проекте необходимо изменить, но в нескольких проектах задействовано много Sql, и если он идентифицируется только вручную один за другим, рабочая нагрузка немного велика. Поэтому он родился, чтобы напрямую изменить источник данных на Mysql, использовать отражение для выполнения методов в Mapper в пакетном режиме, а затем установить начальное значение по умолчанию, если есть параметры, а затем записать успешные данные и неудачные данные, чтобы вы можно изменить в зависимости от причины отказа. Может сэкономить много времени.

Эффект исполнения

Введение кода

Общая идея состоит из трех шагов

  1. Получить все методы класса Mapper для выполнения путем отражения
  2. Получить параметры в методе и присвоить их
  3. воплощать в жизнь
AutoTestMapper autoTestMapper = new AutoTestMapper("存放Mapper全路径名");
autoTestMapper.openSqlSession(sqlSessionFactory);

После того, как в конструктор передано полное имя пути, оно анализируется, имя пакета и все имена файлов анализируются и сохраняются.

    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параметр

        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));
        }

Затем с помощью метода, предоставленного MybatyisgetMapper()Передайте имя класса, чтобы получить нужный класс Mapper. Основным методом являетсяautoTestInvoke()метод

  	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;
    }

На этом логика присвоения начальных значений параметрам и их выполнения завершается.

Инструкции по применению

Автоматический тестовый Mapper может измерить остальные, за исключением того, что параметры передаются как List и Set. Все условия if в xml будут склеены между собой.

  • будетAutoTestMapperскопировано в тестовый модуль. как показано на рисунке

AutoTestMapperфайлы хранятся вgithub

  • существуетresourcesдобавить в модульmybatis-config.xmlФайл, как показано на фиг.

mybatis-config.xmlследует

	<!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="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="连接地址"/>
                <property name="username" value="账号"/>
                <property name="password" value="密码"/>
            </dataSource>
        </environment>
    </environments>
</configuration>
	
  • Создайте папку lib в корневом каталоге, поместите в нее проверенную версию Mybatis и импортируйте этот пакет в Gradle.

compile files('../lib/mybatis-3.5.0-hupengfeiTest.jar') Заполните здесь относительный путь

Если структура каталогов следующая, тоcompile files('lib/mybatis-3.5.0-hupengfeiTest.jar')

mybatis-3.5.0-hupengfeiTest.jarсуществуетgithubв каталоге lib ниже

-lib
	-- mybatis-3.5.0-hupengfeiTest.jar
-build.gradle

Если структура каталогов следующая, тоcompile files('../lib/mybatis-3.5.0-hupengfeiTest.jar')

-lib
	-- mybatis-3.5.0-hupengfeiTest.jar
-service
	-- build.gradle

  • Написать код в тесте подразделения, тест
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { AirApplication.class })//此处AirApplication.class为项目中的启动类,自行修改
public class TestMapper {

    @Test
    public void testCeshi()
            throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException,
            InstantiationException, IOException, ClassNotFoundException {
        //读取Mybatis配置
        Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
        //生成SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
        resourceAsReader.close();
        AutoTestMapper autoTestMapper = new AutoTestMapper(存放Mapper的Java文件夹的全路径名);
        //执行测试方法
        autoTestMapper.openSqlSession(sqlSessionFactory);
    }
}

Неудачный Mapper и его причина будут распечатаны в консоли. Как показано ниже

адрес гитхаба:GitHub.com/Г-н Моду…