反射+註釋,根據實體類物件生成SQL語句工具類
阿新 • • 發佈:2019-01-03
最近在寫一個公司內部專案,由於覺得配置Hibernate過於繁瑣,索性使用了spring的jdbc,可是又要寫很多的sql語句,為了偷偷懶,於是就寫個能通過實體類物件生成SQL語句的工具類。
目前只在MySql資料庫上實驗通過,其他資料庫未測試。
本工具類還有很多不足之處,不過好在可以滿足自己一些簡單的日常使用。
上程式碼了。
欄位型別:
package net.tjnwdseip.util;
public enum FieldType {
STRING,NUMBER,DATE
}
欄位註釋:
表名註釋:package net.tjnwdseip.util; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface FieldAnnotation { String fieldName(); FieldType fieldType(); boolean pk(); }
package net.tjnwdseip.util; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TableAnnotation { String tableName(); }
SQL語句生成工具類:
package net.tjnwdseip.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * * @ClassName: CreateSqlTools * @Description: TODO(根據實體類物件生成SQL語句) * @author LiYang * @date 2012-5-4 下午10:07:03 * */ public class CreateSqlTools { /** * * @Title: getTableName * @Description: TODO(獲取表名) * @param @param obj * @param @return 設定檔案 * @return String 返回型別 * @throws */ private static String getTableName(Object obj) { String tableName = null; if (obj.getClass().isAnnotationPresent(TableAnnotation.class)) { tableName = obj.getClass().getAnnotation(TableAnnotation.class) .tableName(); } return tableName; } /** * * @Title: getAnnoFieldList * @Description: TODO(獲取所有有註釋的欄位,支援多重繼承) * @param @param obj * @param @return 設定檔案 * @return List<Field> 返回型別 * @throws */ @SuppressWarnings("rawtypes") private static List<Field> getAnnoFieldList(Object obj) { List<Field> list = new ArrayList<Field>(); Class superClass = obj.getClass().getSuperclass(); while (true) { if (superClass != null) { Field[] superFields = superClass.getDeclaredFields(); if (superFields != null && superFields.length > 0) { for (Field field : superFields) { if (field.isAnnotationPresent(FieldAnnotation.class)) { list.add(field); } } } superClass = superClass.getSuperclass(); } else { break; } } Field[] objFields = obj.getClass().getDeclaredFields(); if (objFields != null && objFields.length > 0) { for (Field field : objFields) { if (field.isAnnotationPresent(FieldAnnotation.class)) { list.add(field); } } } return list; } /** * * @Title: getFieldValue * @Description: TODO(獲取欄位的值,支援多重繼承) * @param @param obj * @param @param field * @param @return 設定檔案 * @return String 返回型別 * @throws */ @SuppressWarnings({ "rawtypes" }) private static String getFieldValue(Object obj, Field field) { String value = null; String name = field.getName(); String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); Method method = null; Object methodValue = null; try { method = obj.getClass().getMethod(methodName); } catch (NoSuchMethodException | SecurityException e1) { // TODO Auto-generated catch block } if (method != null) { try { methodValue = method.invoke(obj); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block } if (methodValue != null) { value = methodValue.toString(); } else { Class objSuperClass = obj.getClass().getSuperclass(); while (true) { if (objSuperClass != null) { try { methodValue = method.invoke(objSuperClass); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block } if (methodValue != null) { value = methodValue.toString(); break; } else { objSuperClass = objSuperClass.getSuperclass(); } } else { break; } } } } return value; } /** * * @Title: getInsertSql * @Description: TODO(根據實體類物件欄位的值生成INSERT SQL語句,可選固定引數) * @param @param obj * @param @param fixedParams * 固定引數(如該引數與實體類中有相同的欄位,則忽略實體類中的對應欄位,HashMap<String * ,String>,key=指定欄位名,value=對應欄位的值) * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getInsertSql(Object obj, HashMap<String, String> fixedParams) { String insertSql = null; String tableName = getTableName(obj); if (tableName != null) { StringBuffer sqlStr = new StringBuffer("INSERT INTO "); StringBuffer valueStr = new StringBuffer(" VALUES ("); List<Field> annoFieldList = getAnnoFieldList(obj); if (annoFieldList != null && annoFieldList.size() > 0) { sqlStr.append(tableName + " ("); if (fixedParams != null && fixedParams.size() > 0) { Iterator<String> keyNames = fixedParams.keySet().iterator(); while (keyNames.hasNext()) { String keyName = (String) keyNames.next(); sqlStr.append(keyName + ","); valueStr.append(fixedParams.get(keyName) + ","); } } for (Field field : annoFieldList) { FieldAnnotation anno = field .getAnnotation(FieldAnnotation.class); if (!anno.pk()) { Object fieldValue = getFieldValue(obj, field); if (fieldValue != null) { if (fixedParams != null && fixedParams.size() > 0) { Iterator<String> keyNames = fixedParams .keySet().iterator(); boolean nextFieldFlag = false; while (keyNames.hasNext()) { String keyName = (String) keyNames.next(); if (anno.fieldName().equals(keyName)) { nextFieldFlag = true; break; } } if (nextFieldFlag) { break; } } sqlStr.append(anno.fieldName() + ","); switch (anno.fieldType()) { case NUMBER: valueStr.append(fieldValue + ","); break; default: valueStr.append("'" + fieldValue + "',"); break; } } } } insertSql = sqlStr.toString().substring(0, sqlStr.length() - 1) + ")" + valueStr.toString().substring(0, valueStr.length() - 1) + ")"; } } return insertSql; } /** * * @Title: getInsertSql * @Description: TODO(根據實體類物件欄位的值生成INSERT SQL語句) * @param @param obj * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getInsertSql(Object obj) { return getInsertSql(obj, null); } /** * * @Title: getUpdateSql * @Description: TODO(根據實體類物件欄位的值生成UPDATE SQL語句,可選更新條件為主鍵,可選固定更新引數) * @param @param obj * @param @param reqPk 是否指定更新條件為主鍵(true=是,false=否) * @param @param fixedParams * 固定引數(如該引數與實體類中有相同的欄位,則忽略實體類中的對應欄位,HashMap<String * ,String>,key=指定欄位名,value=對應欄位的值) * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getUpdateSql(Object obj, boolean reqPk, HashMap<String, String> fixedParams) { String updateSql = null; String tableName = getTableName(obj); if (tableName != null) { List<Field> annoFieldList = getAnnoFieldList(obj); if (annoFieldList != null && annoFieldList.size() > 0) { StringBuffer sqlStr = new StringBuffer("UPDATE " + tableName); StringBuffer valueStr = new StringBuffer(" SET "); String whereStr = " WHERE "; if (fixedParams != null && fixedParams.size() > 0) { Iterator<String> keyNames = fixedParams.keySet().iterator(); while (keyNames.hasNext()) { String keyName = (String) keyNames.next(); valueStr.append(keyName + "=" + fixedParams.get(keyName) + ","); } } for (Field field : annoFieldList) { String fieldValue = getFieldValue(obj, field); if (fieldValue != null) { FieldAnnotation anno = field .getAnnotation(FieldAnnotation.class); if (!anno.pk()) { if (fixedParams != null && fixedParams.size() > 0) { boolean nextFieldFlag = false; Iterator<String> keyNames = fixedParams .keySet().iterator(); while (keyNames.hasNext()) { String keyName = (String) keyNames.next(); if (anno.fieldName().equals(keyName)) { nextFieldFlag = true; break; } } if (nextFieldFlag) { break; } } valueStr.append(anno.fieldName() + "="); switch (anno.fieldType()) { case NUMBER: valueStr.append(fieldValue + ","); break; default: valueStr.append("'" + fieldValue + "',"); break; } } else { if (reqPk) { whereStr += anno.fieldName() + "=" + fieldValue; } } } } updateSql = sqlStr.toString() + valueStr.toString().substring(0, valueStr.length() - 1) + (reqPk ? whereStr : ""); } } return updateSql; } /** * * @Title: getUpdateSql * @Description: TODO(根據實體類物件欄位的值生成UPDATE SQL語句,無條件) * @param @param obj * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getUpdateSql(Object obj) { return getUpdateSql(obj, false, null); } /** * * @Title: getUpdateSql * @Description: TODO(根據實體類物件欄位的值生成UPDATE SQL語句,可選更新條件為主鍵) * @param @param obj * @param @param reqPk 是否指定更新條件為主鍵(true=是,false=否) * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getUpdateSql(Object obj, boolean reqPk) { return getUpdateSql(obj, reqPk, null); } /** * * @Title: getDeleteSql * @Description: TODO(根據實體類物件欄位的值生成有條件的DELETE * SQL語句,可選主鍵為刪除條件或使用各個欄位的值為條件,多個條件用AND連線) * @param @param obj * @param @param reqPk 是否指定更新條件為主鍵(true=是,false=否) * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getDeleteSql(Object obj, boolean reqPk) { String deleteSql = null; String tableName = getTableName(obj); if (tableName != null) { StringBuffer delSqlBuffer = new StringBuffer("DELETE FROM "); List<Field> annoFieldList = getAnnoFieldList(obj); if (annoFieldList != null && annoFieldList.size() > 0) { delSqlBuffer.append(tableName + " WHERE "); for (Field field : annoFieldList) { if (reqPk) { FieldAnnotation anno = field .getAnnotation(FieldAnnotation.class); if (anno.pk()) { String fieldValue = getFieldValue(obj, field); delSqlBuffer.append(anno.fieldName() + "="); switch (anno.fieldType()) { case NUMBER: delSqlBuffer.append(fieldValue); break; default: delSqlBuffer.append("'" + fieldValue + "'"); break; } break; } } else { String fieldValue = getFieldValue(obj, field); if (fieldValue != null) { FieldAnnotation anno = field .getAnnotation(FieldAnnotation.class); delSqlBuffer.append(anno.fieldName() + "="); switch (anno.fieldType()) { case NUMBER: delSqlBuffer.append(fieldValue + " AND "); break; default: delSqlBuffer .append("'" + fieldValue + "' AND "); break; } } } } if (reqPk) { deleteSql = delSqlBuffer.toString(); } else { deleteSql = delSqlBuffer.toString().substring(0, delSqlBuffer.length() - 5); } } } return deleteSql; } /** * * @Title: getDeleteSql * @Description: TODO(根據實體類物件欄位的值生成有條件的DELETE SQL語句,使用各個欄位的值為條件,多個條件用AND連線) * @param @param obj * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getDeleteSql(Object obj) { return getDeleteSql(obj, false); } /** * * @Title: getSelectAllSql * @Description: TODO(根據實體類物件欄位的值生成SELECT SQL語句,無查詢條件) * @param @param obj * @param @return 設定檔案 * @return String 返回型別 * @throws */ public static String getSelectAllSql(Object obj) { String selectSql = null; String tableName = getTableName(obj); if (tableName != null) { StringBuffer selectBuffer = new StringBuffer("SELECT "); List<Field> annoFieldList = getAnnoFieldList(obj); if (annoFieldList != null && annoFieldList.size() > 0) { for (Field field : annoFieldList) { FieldAnnotation anno = field .getAnnotation(FieldAnnotation.class); selectBuffer.append(anno.fieldName() + ","); } selectSql = selectBuffer.toString().substring(0, selectBuffer.length() - 1) + " FROM " + tableName; } } return selectSql; } }
實體類註釋寫法:
package net.tjnwdseip.entity;
import java.sql.Timestamp;
import net.tjnwdseip.util.FieldAnnotation;
import net.tjnwdseip.util.FieldType;
public class BaseEntity {
@FieldAnnotation(fieldName="id",fieldType=FieldType.NUMBER,pk=true)
private Integer id;
@FieldAnnotation(fieldName="createDate",fieldType=FieldType.DATE, pk = false)
private Timestamp createDate;
@FieldAnnotation(fieldName="modifyDate",fieldType=FieldType.DATE, pk = false)
private Timestamp modifyDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Timestamp getCreateDate() {
return createDate;
}
public void setCreateDate(Timestamp createDate) {
this.createDate = createDate;
}
public Timestamp getModifyDate() {
return modifyDate;
}
public void setModifyDate(Timestamp modifyDate) {
this.modifyDate = modifyDate;
}
public BaseEntity(Integer id, Timestamp createDate, Timestamp modifyDate) {
super();
this.id = id;
this.createDate = createDate;
this.modifyDate = modifyDate;
}
public BaseEntity() {
super();
}
}
package net.tjnwdseip.entity;
import java.sql.Timestamp;
import net.tjnwdseip.util.FieldAnnotation;
import net.tjnwdseip.util.FieldType;
import net.tjnwdseip.util.TableAnnotation;
/**
*
* @ClassName: SysNetProxyCfg
* @Description: TODO(網路代理設定)
* @author LiYang
* @date 2012-5-2 下午4:13:08
*
*/
@TableAnnotation(tableName="sysNetProxyCfg")
public class SysNetProxyCfg extends BaseEntity {
@FieldAnnotation(fieldName = "name", fieldType = FieldType.STRING, pk = false)
private String name;
@FieldAnnotation(fieldName = "type", fieldType = FieldType.STRING, pk = false)
private String type;
@FieldAnnotation(fieldName = "proxyHostIp", fieldType = FieldType.STRING, pk = false)
private String proxyHostIp;
@FieldAnnotation(fieldName = "proxyPort", fieldType = FieldType.NUMBER, pk = false)
private Integer proxyPort;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getProxyHostIp() {
return proxyHostIp;
}
public void setProxyHostIp(String proxyHostIp) {
this.proxyHostIp = proxyHostIp;
}
public Integer getProxyPort() {
return proxyPort;
}
public void setProxyPort(Integer proxyPort) {
this.proxyPort = proxyPort;
}
public SysNetProxyCfg(Integer id, Timestamp createDate,
Timestamp modifyDate, String name, String type, String proxyHostIp,
Integer proxyPort) {
super(id, createDate, modifyDate);
this.name = name;
this.type = type;
this.proxyHostIp = proxyHostIp;
this.proxyPort = proxyPort;
}
public SysNetProxyCfg() {
super();
}
}
測試類:
package net.tjnwdseip.demo;
import java.sql.Timestamp;
import java.util.HashMap;
import net.tjnwdseip.entity.SysNetProxyCfg;
import net.tjnwdseip.util.CreateSqlTools;
public class DemoTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
SysNetProxyCfg netProxyCfg = new SysNetProxyCfg(1, Timestamp.valueOf("2012-05-04 14:45:35"), null, "netProxyCfgName", "netProxyCfgType", "000.000.000.000", 0);
HashMap<String, String> fixedParams=new HashMap<String,String>();
fixedParams.put("createDate", "NOW()");
fixedParams.put("modifyDate", "NOW()");
System.out.println(CreateSqlTools.getDeleteSql(netProxyCfg));
System.out.println(CreateSqlTools.getDeleteSql(netProxyCfg, true));
System.out.println(CreateSqlTools.getInsertSql(netProxyCfg));
System.out.println(CreateSqlTools.getInsertSql(netProxyCfg, fixedParams));
System.out.println(CreateSqlTools.getSelectAllSql(netProxyCfg));
System.out.println(CreateSqlTools.getUpdateSql(netProxyCfg));
System.out.println(CreateSqlTools.getUpdateSql(netProxyCfg, true));
System.out.println(CreateSqlTools.getUpdateSql(netProxyCfg, true, fixedParams));
}
}
測試結果:
DELETE FROM sysNetProxyCfg WHERE id=1 AND createDate='2012-05-04 14:45:35.0' AND name='netProxyCfgName' AND type='netProxyCfgType' AND proxyHostIp='000.000.000.000' AND proxyPort=0
DELETE FROM sysNetProxyCfg WHERE id=1
INSERT INTO sysNetProxyCfg (createDate,name,type,proxyHostIp,proxyPort) VALUES ('2012-05-04 14:45:35.0','netProxyCfgName','netProxyCfgType','000.000.000.000',0)
INSERT INTO sysNetProxyCfg (modifyDate,createDate) VALUES (NOW(),NOW())
SELECT id,createDate,modifyDate,name,type,proxyHostIp,proxyPort FROM sysNetProxyCfg
UPDATE sysNetProxyCfg SET createDate='2012-05-04 14:45:35.0',name='netProxyCfgName',type='netProxyCfgType',proxyHostIp='000.000.000.000',proxyPort=0
UPDATE sysNetProxyCfg SET createDate='2012-05-04 14:45:35.0',name='netProxyCfgName',type='netProxyCfgType',proxyHostIp='000.000.000.000',proxyPort=0 WHERE id=1
UPDATE sysNetProxyCfg SET modifyDate=NOW(),createDate=NOW() WHERE id=1