基於反射+註解+迭代+泛型實現的一對多查詢方法
阿新 • • 發佈:2018-12-20
主要是加入兩個新註解
一個Entity註解,加在類的實體屬性上
/**
* 實體物件屬性的註解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
//表名註解
String table();
//對應的非實體物件屬性名
String field();
//實體類地址
String address();
//名稱
String name();
}
另一個為類似於外來鍵的註解,只不過是外來鍵所對應的屬性
/**
* 外來鍵註解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Key {
//對應Entity註解的表名
String farther();
}
構造實體類如下
@Table(name = "first_type") public class FirstType implements Serializable{ /** * 書本一級型別id */ @Id(name = "id") @Column(name = "id") private String id; /** * 書本一級型別名稱 */ @Column(name = "name") private String name; /** *刪除標記,0正常,1刪除 */ @Column(name = "del_flag") private Integer deleteFlag; @Entity(table = "sub_type",field = "id",address = "cn.keduox.entity.SubType",name = "subTypeList") List<SubType> subTypeList=new ArrayList<>(); public Integer getDeleteFlag() { return deleteFlag; } public void setDeleteFlag(Integer deleteFlag) { this.deleteFlag = deleteFlag; } public FirstType(String id, String name, List<SubType> subTypeList) { this.id = id; this.name = name; this.subTypeList = subTypeList; } public List<SubType> getSubTypeList() { return subTypeList; } public void setSubTypeList(List<SubType> subTypeList) { this.subTypeList = subTypeList; } public FirstType() { } public FirstType(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Table(name = "sub_type") public class SubType implements Serializable{ /** * id */ @Id(name = "id") @Column(name = "id") private String id; /** * 名稱 */ @Column(name = "name") private String name; /** * 所屬父型別id */ @Column(name = "first_type_id") @Key(farther = "sub_type") private String firstTypeId; /** * 所屬父型別 */ private FirstType firstType; /** * 包含的子型別 */ @Entity(table = "second_type",field = "id",address = "cn.keduox.entity.SecondType",name = "secondTypeList") List<SecondType> secondTypeList=new ArrayList<>(); public Integer getDeleteFlag() { return deleteFlag; } public void setDeleteFlag(Integer deleteFlag) { this.deleteFlag = deleteFlag; } /** *刪除標記,0正常,1刪除 */ @Column(name = "del_flag") private Integer deleteFlag; public SubType(String id, String name, String firstTypeId) { this.id = id; this.name = name; this.firstTypeId = firstTypeId; } public SubType() { } public SubType(String id, String name, String firstTypeId, FirstType firstType, List<SecondType> secondTypeList) { this.id = id; this.name = name; this.firstTypeId = firstTypeId; this.firstType = firstType; this.secondTypeList = secondTypeList; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFirstTypeId() { return firstTypeId; } public void setFirstTypeId(String firstTypeId) { this.firstTypeId = firstTypeId; } public FirstType getFirstType() { return firstType; } public void setFirstType(FirstType firstType) { this.firstType = firstType; } public List<SecondType> getSecondTypeList() { return secondTypeList; } public void setSecondTypeList(List<SecondType> secondTypeList) { this.secondTypeList = secondTypeList; } }
BaseDaoImpl的查詢方法如下:
/**
* 查詢方法:僅封裝了where和預設的order by以及分頁,支援模糊查詢
*
* @param t 要查的表
* @param open 是否啟用排序
* @param flag 排序要求
* @param e 分頁物件
* @param vague 是否進行模糊查詢
* @return
*/
@Override
public List<T> select(T t, boolean open, boolean flag, E e, boolean vague,String order) throws Exception {
//獲取表名註解
Table table = EntityClass.getAnnotation(Table.class);
String tableName = table.name();
//取的域物件並做遍歷處理
Field[] fields = EntityClass.getDeclaredFields();
//存放where語句後的查詢條件的Map
Map<String, Object> whereMap = new HashMap<String, Object>();
List<Object> sonObjectList = new ArrayList<>();
//存放排序條件的集合
List<String> orderList = new ArrayList<String>();
for (Field field : fields) {
field.setAccessible(true);//一定要施暴
//獲取屬性值,判斷是否為空,拼接where條件
if (field.isAnnotationPresent(Column.class)) {
/* Method method=clazz.getMethod("get"+getMethodName(field.getName()));Object value=method.invoke(object);PropertyDescriptor pd = new PropertyDescriptor(field.getName(),object.getClass());Object value=pd.getReadMethod().invoke(object);String verificationValue= (String) field.get(object);*/
Method method = EntityClass.getMethod("get" + getMethodName(field.getName()));
String verificationValue = String.valueOf(method.invoke(t));
if (!verificationValue.equals("null")) {
//不為空,是查詢條件
Object value = field.get(t);
Class clazz = value.getClass();
Column column = field.getAnnotation(Column.class);
String key = column.name();
whereMap.put(key, value);
}
}
//拼接排序條件
if (field.isAnnotationPresent(OrderItem.class)) {
OrderItem orderItem = field.getAnnotation(OrderItem.class);
orderList.add(orderItem.name());
}
}
//拼接分頁
Integer[] limitCondition = new Integer[2];
Field[] fields1 = EntityClass1.getDeclaredFields();
for (Field field : fields1) {
if (field.isAnnotationPresent(Column.class)) {
Column column = field.getAnnotation(Column.class);
String limitName = column.name();
Method method = EntityClass1.getMethod("get" + getMethodName(field.getName()));
Integer value = (Integer) method.invoke(e);
if (value != null) {
if (limitName.equals("currentPage")) {
limitCondition[0] = value;
}
if (limitName.equals("currentCount")) {
limitCondition[1] = value;
}
}
}
}
if (limitCondition[0] != null && limitCondition[1] != null) {
limitCondition[0] = limitCondition[1] * (limitCondition[0] - 1);
}
//集合準備完畢,開始拼接sql
StringBuilder sql = new StringBuilder("");
sql.append("select * from ").append(tableName);
//判斷whereMap是否為空來進行條件查詢
List<Object> valueList = new ArrayList<>();
if (whereMap.size() != 0) {
sql.append(" where ");
for (Map.Entry<String, Object> entry : whereMap.entrySet()) {
if (vague) {
if (entry.getValue() instanceof String) {
sql.append(entry.getKey() + " like ? and ");
valueList.add("%" + entry.getValue() + "%");
} else {
sql.append(entry.getKey() + "=? and ");
valueList.add(entry.getValue());
}
} else {
sql.append(entry.getKey() + "=? and ");
valueList.add(entry.getValue());
}
}
sql.delete(sql.length() - 5, sql.length());
}
//判斷是否進行預設排序
if (open) {
sql.append(" order by ");
if (orderList.size() != 0) {
for (String str : orderList) {
sql.append(str).append(",");
}
sql.delete(sql.length() - 1, sql.length());
}
}
//是否進行自定義排序
if(!(order==null || order.equals(""))){
if (open){
boolean f=true;
for (String str : orderList) {
if (str.equals(order)){
f=false;
break;
}
}
if (f){
sql.append(",").append(order+" ");
}
}else {
sql.append(" order by ").append(order+" ");
}
}
if (open || !(order==null || order.equals(""))){
sql.append(" ").append(flag == true ? "asc" : "desc").append(" ");
}
//判斷是否分頁
if (limitCondition[0] != null && limitCondition[1] != null) {
sql.append("limit").append(" ").append(limitCondition[0]).append(",").append(limitCondition[1]);
}
//SQL拼接完畢,開始執行查詢
PreparedStatement preState = null;
Connection connection = null;
ResultSet resultSet = null;
try {
connection = JDBCUtils.getConnection();
//編譯
preState = connection.prepareStatement(String.valueOf(sql));
preState = JDBCUtils.setObject(preState, valueList.toArray());
resultSet = preState.executeQuery();
//通過反射將resultSet封裝為物件集
List<T> resultList = new ArrayList<>();
int m=resultSet.getRow();
while (resultSet.next()) {
T resultObject = EntityClass.newInstance();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(Column.class)) {
String columnName = field.getAnnotation(Column.class).name();
Object fieldValue = resultSet.getObject(columnName);
field.set(resultObject, fieldValue);
}
}
for (Field field : fields) {
//處理實體類註解,採用迭代
if (field.isAnnotationPresent(Entity.class)) {
//獲取註解物件,獲取對應的屬性值
Entity entity = field.getAnnotation(Entity.class);
String idName = entity.field();
Method method = EntityClass.getMethod("get" + getMethodName(idName));
String verificationValue = String.valueOf(method.invoke(t));
Class clazz = Class.forName(entity.address());
Object sonObject = clazz.newInstance();
Object value;
if (!verificationValue.equals("null")) {
//這是條件查詢
value = method.invoke(t);
} else {
//非條件查詢
value = method.invoke(resultObject);
}
Field[] sonFields = sonObject.getClass().getDeclaredFields();
//獲取子實體類的id屬性
for (Field field1 : sonFields) {
field1.setAccessible(true);//一定要施暴
//獲取外來鍵
if (field1.isAnnotationPresent(Key.class)) {
if (field1.getAnnotation(Key.class).farther().equals(entity.table())) {
field1.set(sonObject, value);
break;
}
}
}
sonObjectList = sonSelect(sonObject);
//封裝
//判斷當前域物件的型別用getSimpleName
Class c = field.getType();
String name = c.getSimpleName();
if ( sonObjectList != null && sonObjectList.size() != 0) {
if ("List".equals(name)) {
field.set(resultObject, sonObjectList);
} else {
field.set(resultObject, sonObjectList.get(0));
}
}
}
}
resultList.add(resultObject);
}
return resultList;
} catch (SQLException e1) {
e1.printStackTrace();
return null;
} finally {
//關閉資源
JDBCUtils.close(connection, preState, resultSet);
}
}
/**
* 迭代處理類
*/
public List<Object> sonSelect(Object object) throws Exception {
Class clazz = object.getClass();
Table table = (Table) clazz.getAnnotation(Table.class);
String tableName = table.name();
Field[] fieldList = clazz.getDeclaredFields();
Map<String, Object> whereMap = new HashMap<>();
List<Object> sonObjectList = new ArrayList<>();
for (Field field : fieldList) {
field.setAccessible(true);
//普通型別註解
if (field.isAnnotationPresent(Column.class)) {
Method method = clazz.getMethod("get" + getMethodName(field.getName()));
String verificationValue = String.valueOf(method.invoke(object));
if (!verificationValue.equals("null")) {
Object value = method.invoke(object);
String key = field.getAnnotation(Column.class).name();
whereMap.put(key, value);
}
}
}
//集合準備完畢,開始拼接sql
StringBuilder sql = new StringBuilder("");
sql.append("select * from ").append(tableName);
List<Object> valueList = new ArrayList<>();
if (whereMap.size() != 0) {
sql.append(" where ");
for (Map.Entry<String, Object> entry : whereMap.entrySet()) {
sql.append(entry.getKey() + "=? and ");
valueList.add(entry.getValue());
}
sql.delete(sql.length() - 5, sql.length());
}
//SQL拼接完畢,開始執行查詢
PreparedStatement preState = null;
Connection connection = null;
ResultSet resultSet = null;
try {
connection = JDBCUtils.getConnection();
//編譯
preState = connection.prepareStatement(String.valueOf(sql));
preState = JDBCUtils.setObject(preState, valueList.toArray());
resultSet = preState.executeQuery();
//通過反射將resultSet封裝為物件集
List<Object> resultList = new ArrayList<>();
while (resultSet.next()) {
Object resultObject = clazz.newInstance();
for (Field field : fieldList) {
field.setAccessible(true);
//普通註解
if (field.isAnnotationPresent(Column.class)) {
String columnName = field.getAnnotation(Column.class).name();
Object fieldValue = resultSet.getObject(columnName);
field.set(resultObject, fieldValue);
}
}
for (Field field : fieldList) {
//處理實體類註解,採用迭代
if (field.isAnnotationPresent(Entity.class)) {
Entity entity = field.getAnnotation(Entity.class);
String idName = entity.field();
Method method = clazz.getMethod("get" + getMethodName(idName));
String verificationValue = String.valueOf(method.invoke(object));
Class clazz1 = Class.forName(entity.address());
Object sonObject = clazz1.newInstance();
Object value;
if (!verificationValue.equals("null")) {
//條件查詢
value = method.invoke(object);
} else {
value = method.invoke(resultObject);
}
Field[] sonFields = sonObject.getClass().getDeclaredFields();
for (Field field2 : sonFields) {
field2.setAccessible(true);//一定要施暴
if (field2.isAnnotationPresent(Key.class)) {
if (field2.getAnnotation(Key.class).farther().equals(entity.table())) {
field2.set(sonObject, value);
break;
}
}
}
sonObjectList = sonSelect(sonObject);
//封裝
//判斷註解是否是加在集合上的
//判斷當前域物件的型別用getSimpleName
Class c = field.getType();
String name = c.getSimpleName();
if (sonObjectList != null && sonObjectList.size() !=0) {
if ("List".equals(name)) {
field.set(resultObject, sonObjectList);
} else {
field.set(resultObject, sonObjectList.get(0));
}
}
}
}
resultList.add(resultObject);
}
return resultList;
} catch (SQLException e1) {
e1.printStackTrace();
return null;
} finally {
//關閉資源
JDBCUtils.close(connection, preState, resultSet);
}
}
這樣,在查詢一級類的時候就能把二級類的資訊也查詢出來了,同時可以無限迭代查詢。
程式碼下載地址:https://download.csdn.net/download/qq_34295546/10225638