idea中出現sql語句錯誤提示:【the right syntax to use near ‘‘ 】的解決方法
阿新 • • 發佈:2021-04-29
記錄一下這個坑,這是一個有關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;
}
}