idea中出现sql语句错误提示:【the right syntax to use near ‘‘ 】的解决方法

记录一下这个坑,这是一个有关idea显示问题导致无法检查出错误的坑

idea中报错信息

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1

我的错误代码

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

/**
 * 该类使用约束:
 * 表名及字段名等要与相应POJO一致
 * 但是表名及字段名等单词用下划线分隔,而POJO中类名(即代表的关系名、表名)使用大坨峰,
 * 而成员属性名(即字段名)使用小驼峰
 *
 * @param <T> 所要操作POJO类型
 */
public class JdbcUtils<T> {
    public static String driver = null; //数据库驱动
    public static String url = null;    //数据库地址
    public static String user = null;//数据库用户
    public static String password = null;//数据库用户密码
    public static HashMap<Class<?>, Method> ptmtMap = new HashMap<>();//PrepareStatement设置sql中?内容的【属性类型】到【相应方法】的映射
    public static HashMap<Class<?>, Method> rsMap = new HashMap<>();//ResultSet中获取sql执行结果集中每条记录的【相应字段】到【相应方法】的映射
    public static HashMap<Class<?>, Class<?>> primaryClassMap = new HashMap<>();//设置基本类型到原始类型的转换
    private String sql = null; //执行的sql语句
    private Connection conn = null;//数据库连接对象
    private Statement stmt = null;//数据库执行对象
    private PreparedStatement ptmt = null;//数据库执行对象
    private ResultSet rs = null;//数据库执行结果集
    private Integer rowCount = null;   // 表示执行executeUpdate方法时的返回值,代表改动的记录数(即行数)
    private boolean isExecute = false; // 表示执行execute方法时的返回值,若执行成功则为true,否则为false

    /**
     * 用于加载数据库驱动
     */
    private static void loadDriver() {
        try {
//            读取数据库配置文件
            FileInputStream fis = new FileInputStream("D:\\ideaProject\\javaweb-maven\\jdbcUtils\\src\\main\\resources\\jdbc.properties");
            Properties properties = new Properties();
            properties.load(fis);
            fis.close();
            driver = properties.getProperty("jdbc.driver");
            url = properties.getProperty("jdbc.url");
            user = properties.getProperty("jdbc.user");
            password = properties.getProperty("jdbc.password");
            Class.forName(driver);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 【各种类型】与【PrepareStatement中设置方法】所对应的HashMap关系表
     */
    private static void setPtmtMap(PreparedStatement ptmt) {
        Class<PreparedStatement> ptmtClass = (Class<PreparedStatement>) ptmt.getClass();
        Method[] methods = ptmtClass.getMethods();
        String pattern = "^set[A-Z][\\w]*";//使用过滤不是设置sql语句问号内容的方法的正则表达式
        for (Method method : methods) {
            String methodName = method.getName();
            boolean isMatch = Pattern.matches(pattern, methodName);
            if (!isMatch)
                continue;
            if (method.getParameterCount() != 2)//该工具只用【设置sql语句问号内容】只有2个参数的方法
                continue;
            Class[] classes = method.getParameterTypes();
            String className = classes[1].getSimpleName();
            if (methodName.equalsIgnoreCase("set" + className)) //进一步判断是否为setXxxx方法
                ptmtMap.put(classes[1], method);
        }
    }

    /**
     * 【各种类型】与【ResultSet中获取方法】所对应的HashMap关系表
     */
    private static void setRsMap(PreparedStatement ptmt) {
        try {
            Class<ResultSet> rsClass = (Class<ResultSet>) ptmt.executeQuery().getClass();
            Method[] methods = rsClass.getMethods();
            String pattern = "^get[A-Z][\\w]*";//通过获取字段方法名称中开头都含有【getX】规律,
            // 设置过滤不是获取查询结果字段值的方法的正则表达式
            for (Method method : methods) {
                String methodName = method.getName();
                boolean isMatch = Pattern.matches(pattern, methodName);
                if (!isMatch)
                    continue;
                if (method.getParameterCount() != 1)//进一步过滤,由于获取字段方法通常只有1个形参
                    continue;
                Class returnType = method.getReturnType();
                rsMap.put(returnType, method);//根据方法的返回值建立映射
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static void setPrimaryClassMap() {
        primaryClassMap.put(Integer.class, int.class);
        primaryClassMap.put(Double.class, double.class);
        primaryClassMap.put(Float.class, float.class);
    }

    static {
        loadDriver();
        Connection conn = null;
        PreparedStatement ptmt = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
            ptmt = conn.prepareStatement("select database()");
            setPtmtMap(ptmt);
            setRsMap(ptmt);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ptmt != null) {
                try {
                    ptmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        setPrimaryClassMap();
    }

    public JdbcUtils() {
    }

    /**
     * 连接数据库
     *
     * @return 若成功返回true,否则返回false
     */
    public boolean connect() {
        try {
            conn = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn != null;
    }

    /**
     * 按封装好的POJO对象查找条件,执行查找操作
     *
     * @param obj 封装好的查找条件
     * @return 查找后的ArrayList结果集
     */
    public List<T> ptmtQuery(T obj) {
        sql = "select * from ";
        String classSimpleName = obj.getClass().getSimpleName();
        sql += toStdName(classSimpleName);
        if (!addCondition(obj) || !setQuestionMarkContent(1, obj)) {
            return null;
        }
        try {
            System.out.println(sql);
            rs = ptmt.executeQuery();
//            rs = ptmt.executeQuery("select * from student where 1=1 and id=1 and age=18");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return toArrayList();
    }

    /**
     * @param index 所设置问号开始的下标
     * @param obj   问号设置的内容,要封装成POJO对象
     * @return 若设置成功返回true,否则返回false
     */
    public boolean setQuestionMarkContent(int index, T obj) {
        try {
            ptmt = conn.prepareStatement(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                Object fieldValue = field.get(obj);
                if (fieldValue == null)
                    continue;
                Class<?> fieldClass = field.getType();
                if (primaryClassMap.get(fieldClass) != null) {
                    fieldClass = primaryClassMap.get(fieldClass);
                }
                Method method = ptmtMap.get(fieldClass);
                method.invoke(ptmt, index++, fieldValue);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 给当前sql语句添加查询或者删除、修改的条件。即“where XXX”
     *
     * @param obj 条件封装成的POJO对象
     * @return 若设置成功返回true,否则返回false
     */
    public boolean addCondition(T obj) {
        Class tClass = obj.getClass();
        Field[] declaredFields = tClass.getDeclaredFields();
        sql += " where 1=1";
        for (Field field : declaredFields) {
            String key = toStdName(field.getName());
            field.setAccessible(true);
            try {
                if (field.get(obj) != null) {
                    sql += " and " + key + "=?";
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 将数据库中的表名、字段名等转换为规定的名字
     *
     * @param name 表名(即关系名)
     * @return 修改后的名字
     */
    public String toStdName(String name) {
        char[] nameChars = name.toCharArray();
        char[] s = new char[name.length() * 2];
        int len = 0;
        if (nameChars.length > 0) {
            if ((nameChars[0] & 0x20) != 0) //通过ASCII码规律,判断是否为大小写
                s[len++] = nameChars[0];
            else
                s[len++] = (char) (nameChars[0] + 32);//转换为小写
        }
        for (int i = 1; i < nameChars.length; i++) {
            char c = nameChars[i];
            if ((c & 0x20) != 0) {  //通过ASCII码规律,判断是否为大小写
                s[len++] = c;
            } else {
                s[len++] = '_';
                s[len++] = (char) (c + 32);//转换为小写
            }
        }
        s[len] = '\0';
        return String.valueOf(s);
    }

    /**
     * 将结果集转换为ArrayList<T>对象
     *
     * @return 若成功,则返回结果集转换的ArrayList<T>对象;否则返回null
     */
    public List<T> toArrayList() {
        if (rs == null)
            return null;
        List<T> list = new ArrayList<>();
        //获取泛型的Class对象
        Class<T> tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Constructor<T> constructor = null;
        Field[] fields = tClass.getDeclaredFields();
        try {
            constructor = tClass.getConstructor();
            while (rs.next()) {
                T obj = constructor.newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    Method method = rsMap.get(field.getType());
                    Object value = method.invoke(rs, toStdName(field.getName()));
                    field.set(obj, value);
                }
                list.add(obj);
            }
        } catch (SQLException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
            return null;
        }
        return list;
    }
}

我的测试代码

    @Test
    public void ptmtQuery() {
        JdbcUtils<Student> jdbcUtils = new JdbcUtils<>();
        Student stu = new Student(null, "小明", null, null);
        jdbcUtils.connect();
        System.out.println(jdbcUtils.ptmtQuery(stu));
    }

idea报错完整信息

"C:\Program Files\Java\jdk-12.0.1\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 -Didea.launcher.port=61892 "-Didea.launcher.bin.path=D:\Program Files (x86)\IntelliJ IDEA 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files (x86)\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar;D:\Program Files (x86)\IntelliJ IDEA 2018.2.5\plugins\junit\lib\junit-rt.jar;D:\Program Files (x86)\IntelliJ IDEA 2018.2.5\plugins\junit\lib\junit5-rt.jar;D:\ideaProject\javaweb-maven\jdbcUtils\target\test-classes;D:\ideaProject\javaweb-maven\jdbcUtils\target\classes;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\junit\junit\4.11\junit-4.11.jar;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\mysql\mysql-connector-java\8.0.23\mysql-connector-java-8.0.23.jar;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\com\google\protobuf\protobuf-java\3.11.4\protobuf-java-3.11.4.jar;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\javax\servlet\jsp\jsp-api\2.1\jsp-api-2.1.jar;D:\Program Files (x86)\webpage editing tools\apache-maven-3.5.4\repo\org\apache\taglibs\taglibs-standard-impl\1.2.5\taglibs-standard-impl-1.2.5.jar" com.intellij.rt.execution.application.AppMainV2 com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 JdbcUtilsTest,ptmtQuery
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1003)
	at JdbcUtils.ptmtQuery(JdbcUtils.java:173)
	at JdbcUtilsTest.ptmtQuery(JdbcUtilsTest.java:17)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
null
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)

Process finished with exit code 0

错误原因分析

idea一直报sql语法出现错误,但是通过调试看到的情况如下:
在这里插入图片描述
可以明显看出sql语法没有出现错误,但是这只是被idea给欺骗了,idea在这里显示的字符串是经过处理的。不信,可以复制sql变量的值到txt文本中,我们可以发现,粘贴过去的字符串显示如下:
在这里插入图片描述
可以看到"student"和"student_name"两个位置后面出现了很多空格,这是为什么呢?
接下来,我们去看源码,就能知道问题的原因了
以上两个位置的字符串都是经过一个toStdName的方法处理后才拼接到sql变量中的,问题就出在这个toStdName方法

public String toStdName(String name) {
        char[] nameChars = name.toCharArray();
        char[] s = new char[name.length() * 2];
        int len = 0;
        if (nameChars.length > 0) {
            if ((nameChars[0] & 0x20) != 0) //通过ASCII码规律,判断是否为大小写
                s[len++] = nameChars[0];
            else
                s[len++] = (char) (nameChars[0] + 32);//转换为小写
        }
        for (int i = 1; i < nameChars.length; i++) {
            char c = nameChars[i];
            if ((c & 0x20) != 0) {  //通过ASCII码规律,判断是否为大小写
                s[len++] = c;
            } else {
                s[len++] = '_';
                s[len++] = (char) (c + 32);//转换为小写
            }
        }
        s[len] = '\0'; //此处设置结尾字符
        return String.valueOf(s); 
    }

问题就出在这里

		s[len] = '\0'; //此处设置结尾字符
        return String.valueOf(s); //问题就出在这里,字符数组s的长度是原先传进去的字符串长度的两倍,而String.valueOf这个方法虽然能将s数组转换为字符串,但是它不会以设置的'\0'作为结尾,导致其长度为数组长度,而不是为字符串长度,而idea又出于某种原因,导致显示的是以'\0'作为结尾的字符串内容

又因为PrepareStatement的sql语句中不能出现多余空格,所以导致sql语法报错。结果在加上,idea的显示问题,导致这个错误很难被发现,这真是一个坑

修改后的正确代码如下

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

/**
 * 该类使用约束:
 * 表名及字段名等要与相应POJO一致
 * 但是表名及字段名等单词用下划线分隔,而POJO中类名(即代表的关系名、表名)使用大坨峰,
 * 而成员属性名(即字段名)使用小驼峰
 *
 * @param <T> 所要操作POJO类型
 */
public class JdbcUtils<T> {
    public static String driver = null; //数据库驱动
    public static String url = null;    //数据库地址
    public static String user = null;//数据库用户
    public static String password = null;//数据库用户密码
    public static HashMap<Class<?>, Method> ptmtMap = new HashMap<>();//PrepareStatement设置sql中?内容的【属性类型】到【相应方法】的映射
    public static HashMap<Class<?>, Method> rsMap = new HashMap<>();//ResultSet中获取sql执行结果集中每条记录的【相应字段】到【相应方法】的映射
    public static HashMap<Class<?>, Class<?>> primaryClassMap = new HashMap<>();//设置基本类型到原始类型的转换
    private String sql = null; //执行的sql语句
    private Connection conn = null;//数据库连接对象
    private Statement stmt = null;//数据库执行对象
    private PreparedStatement ptmt = null;//数据库执行对象
    private ResultSet rs = null;//数据库执行结果集
    private Integer rowCount = null;   // 表示执行executeUpdate方法时的返回值,代表改动的记录数(即行数)
    private boolean isExecute = false; // 表示执行execute方法时的返回值,若执行成功则为true,否则为false

    /**
     * 用于加载数据库驱动
     */
    private static void loadDriver() {
        try {
//            读取数据库配置文件
            FileInputStream fis = new FileInputStream("D:\\ideaProject\\javaweb-maven\\jdbcUtils\\src\\main\\resources\\jdbc.properties");
            Properties properties = new Properties();
            properties.load(fis);
            fis.close();
            driver = properties.getProperty("jdbc.driver");
            url = properties.getProperty("jdbc.url");
            user = properties.getProperty("jdbc.user");
            password = properties.getProperty("jdbc.password");
            Class.forName(driver);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 【各种类型】与【PrepareStatement中设置方法】所对应的HashMap关系表
     */
    private static void setPtmtMap(PreparedStatement ptmt) {
        Class<PreparedStatement> ptmtClass = (Class<PreparedStatement>) ptmt.getClass();
        Method[] methods = ptmtClass.getMethods();
        String pattern = "^set[A-Z][\\w]*";//使用过滤不是设置sql语句问号内容的方法的正则表达式
        for (Method method : methods) {
            String methodName = method.getName();
            boolean isMatch = Pattern.matches(pattern, methodName);
            if (!isMatch)
                continue;
            if (method.getParameterCount() != 2)//该工具只用【设置sql语句问号内容】只有2个参数的方法
                continue;
            Class[] classes = method.getParameterTypes();
            String className = classes[1].getSimpleName();
            if (methodName.equalsIgnoreCase("set" + className)) //进一步判断是否为setXxxx方法
                ptmtMap.put(classes[1], method);
        }
    }

    /**
     * 【各种类型】与【ResultSet中获取方法】所对应的HashMap关系表
     */
    private static void setRsMap(PreparedStatement ptmt) {
        try {
            Class<ResultSet> rsClass = (Class<ResultSet>) ptmt.executeQuery().getClass();
            Method[] methods = rsClass.getMethods();
            String pattern = "^get[A-Z][\\w]*";//通过获取字段方法名称中开头都含有【getX】规律,
            // 设置过滤不是获取查询结果字段值的方法的正则表达式
            for (Method method : methods) {
                String methodName = method.getName();
                boolean isMatch = Pattern.matches(pattern, methodName);
                if (!isMatch)
                    continue;
                if (method.getParameterCount() != 1)//进一步过滤,由于获取字段方法通常只有1个形参
                    continue;
                Class returnType = method.getReturnType();
                rsMap.put(returnType, method);//根据方法的返回值建立映射
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static void setPrimaryClassMap() {
        primaryClassMap.put(Integer.class, int.class);
        primaryClassMap.put(Double.class, double.class);
        primaryClassMap.put(Float.class, float.class);
    }

    static {
        loadDriver();
        Connection conn = null;
        PreparedStatement ptmt = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
            ptmt = conn.prepareStatement("select database()");
            setPtmtMap(ptmt);
            setRsMap(ptmt);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ptmt != null) {
                try {
                    ptmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        setPrimaryClassMap();
    }

    public JdbcUtils() {
    }

    /**
     * 连接数据库
     *
     * @return 若成功返回true,否则返回false
     */
    public boolean connect() {
        try {
            conn = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn != null;
    }

    /**
     * 按封装好的POJO对象查找条件,执行查找操作
     *
     * @param obj 封装好的查找条件
     * @return 查找后的ArrayList结果集
     */
    public List<T> ptmtQuery(T obj) {
        sql = "select * from ";
        String classSimpleName = obj.getClass().getSimpleName();
        sql += toStdName(classSimpleName);
        if (!addCondition(obj) || !setQuestionMarkContent(1, obj)) {
            return null;
        }
        try {
//            System.out.println(sql);
            rs = ptmt.executeQuery();
//            rs = ptmt.executeQuery("select * from student where 1=1 and id=1 and age=18");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return toArrayList();
    }

    /**
     * @param index 所设置问号开始的下标
     * @param obj   问号设置的内容,要封装成POJO对象
     * @return 若设置成功返回true,否则返回false
     */
    public boolean setQuestionMarkContent(int index, T obj) {
        try {
            ptmt = conn.prepareStatement(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                Object fieldValue = field.get(obj);
                if (fieldValue == null)
                    continue;
                Class<?> fieldClass = field.getType();
                if (primaryClassMap.get(fieldClass) != null) {
                    fieldClass = primaryClassMap.get(fieldClass);
                }
                Method method = ptmtMap.get(fieldClass);
                method.invoke(ptmt, index++, fieldValue);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 给当前sql语句添加查询或者删除、修改的条件。即“where XXX”
     *
     * @param obj 条件封装成的POJO对象
     * @return 若设置成功返回true,否则返回false
     */
    public boolean addCondition(T obj) {
        Class tClass = obj.getClass();
        Field[] declaredFields = tClass.getDeclaredFields();
        sql += " where 1=1";
        for (Field field : declaredFields) {
            String key = toStdName(field.getName());
            field.setAccessible(true);
            try {
                if (field.get(obj) != null) {
                    sql += " and " + key + "=?";
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 将数据库中的表名、字段名等转换为规定的名字
     *
     * @param name 表名(即关系名)
     * @return 修改后的名字
     */
    public String toStdName(String name) {
        char[] nameChars = name.toCharArray();
        char[] s = new char[name.length() * 2];
        int len = 0;
        if (nameChars.length > 0) {
            if ((nameChars[0] & 0x20) != 0) //通过ASCII码规律,判断是否为大小写
                s[len++] = nameChars[0];
            else
                s[len++] = (char) (nameChars[0] + 32);//转换为小写
        }
        for (int i = 1; i < nameChars.length; i++) {
            char c = nameChars[i];
            if ((c & 0x20) != 0) {  //通过ASCII码规律,判断是否为大小写
                s[len++] = c;
            } else {
                s[len++] = '_';
                s[len++] = (char) (c + 32);//转换为小写
            }
        }
        s[len] = '\0';
        return String.valueOf(s,0,len);
    }

    /**
     * 将结果集转换为ArrayList<T>对象
     *
     * @return 若成功,则返回结果集转换的ArrayList<T>对象;否则返回null
     */
    public List<T> toArrayList() {
        if (rs == null)
            return null;
        List<T> list = new ArrayList<>();
        //获取泛型的Class对象
        Class<T> tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Constructor<T> constructor = null;
        Field[] fields = tClass.getDeclaredFields();
        try {
            constructor = tClass.getConstructor();
            while (rs.next()) {
                T obj = constructor.newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    Method method = rsMap.get(field.getType());
                    Object value = method.invoke(rs, toStdName(field.getName()));
                    field.set(obj, value);
                }
                list.add(obj);
            }
        } catch (SQLException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
            return null;
        }
        return list;
    }
}

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值