生成sql:select
上一篇講了怎樣生成一個sql中where的一部分,之后我們要做事情就簡單很多了,就只要像最開始一樣的生成各種sql語句就好了,之后只要再加上我們需要的條件,一個完整的sql就順利的做好了。
現在我們開始寫生成查詢語句的sql。一個查詢語句大致上是這樣的:
SELECT name, id, create_date, age, mark, status FROM user
這里可以看出來,一個基礎的查詢語句基本上就是一個 SELECT 后面加上需要查詢的字段,跟上 FROM 和要查詢的表名稱就好了。 最多后面可能需要加上 ORDER BY/GROUP BY/LIMIT ....之類的就好了,因為比較簡單,這里就不寫了。(太復雜的就直接寫sql就好了,我自己不需要這種操作)
思路
- 從之前拿到的映射關系中拿到屬性和字段名的映射,然后拼接sql。
- 執行sql,並取出結果。
- 實例化class,使用反射給class的屬性賦值。
這幾步都還是比較好做的,第一步很簡單,仿照着之前寫的就可以了。因為這里在執行sql的時候,我使用的是JdbcTemplate,這里有一個不大不小的坑,下面我說一下。
一個不大不小的坑
這個坑是我在使用我寫好的這個項目給公司做報表的時候碰到的。原因是這樣,因為數據庫中有些字段是datetime類型的,這個字段有時候在表中的值是:0000-00-00 00:00:00,(我也不知道這個值是怎么進去的,但是就是存在/(ㄒoㄒ)/~~)但是這個值是無法轉換成為java中的Date類型。所以這里會報錯。
我在這里寫了一個繼承SpringJdbc中的ColumnMapRowMapper的類,是這樣的:
import org.springframework.jdbc.core.ColumnMapRowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 捕獲取值的錯誤
*
* @author hjx
*/
public class PlusColumnMapRowMapper extends ColumnMapRowMapper {
/**
* 數據庫類型為時間時, 如果值為 0000-00-00 00:00:00
* 會報錯,所以重寫此方法,返回null
*
* @param rs
* @param index
* @return
* @throws SQLException
*/
@Override
protected Object getColumnValue(ResultSet rs, int index) throws SQLException {
Object columnValue = null;
try {
columnValue = super.getColumnValue(rs, index);
} catch (SQLException e) {
e.printStackTrace();
}
return columnValue;
}
}
這個類具體在哪里使用,會在下面說明。
實現
現在說一下怎么實現上面的思路,首先因為第一步比較簡單,就不寫了。我直接從第二步開始。
-
執行sql,並取出結果。
這里我用的是JdbcTemplate的方法,這給我們提供了一個方法:
<T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper)這里前兩個參數比較好理解,一個是sql,一個是sql中的參數。第三個是需要傳一個接口RowMapper
,這個接口具體是干啥的上網一查就知道了~~~ 這里面有一個方法:
T mapRow(ResultSet rs, int rowNum) throws SQLException第一個參數是查詢的結果,第二個是指現在在第幾行結果,返回值是你要返回什么對象。這里我們需要重寫這個方法,把查詢出的結果轉換成為我們需要的對象。我們可以這么寫:
/** * 把數據庫查詢的結果與對象進行轉換 * * @param resultSet * @param rowNum * @return * @throws SQLException */ @Override public T mapRow(ResultSet resultSet, int rowNum) throws SQLException { Map<String, Object> resultMap = columnMapRowMapper.mapRow(resultSet, rowNum); 。。。。這個方法中的columnMapRowMapper 就是上面我們寫的PlusColumnMapRowMapper,它的作用就是將查詢結果第 rowNum 拿出來,並且將結果轉換過成為一個 Map<String, Object>。其中:
key :是表字段名稱。
Object :該字段的值。
上面寫的PlusColumnMapRowMapper主要作用就是在獲取值的時候如果發生異常,返回一個null。
在這一步里我們已經拿到了執行sql的結果,現在我們要將結果轉換過為我們需要的class。
-
將結果轉換為class
在上一步我們拿到了存放結果Map,現在只需要將map遍歷一下,然后實例化java對象,根據字段和屬性的映射關系使用反射將屬性一個個的set進去就好了。現在貼上上一步的完整代碼:
public T mapRow(ResultSet resultSet, int rowNum) throws SQLException { Map<String, Object> resultMap = columnMapRowMapper.mapRow(resultSet, rowNum); T instance = getInstance(tableClass); for (Map.Entry<String, Object> entry : resultMap.entrySet()) { //數據庫字段名 String key = entry.getKey(); if (!columnFieldMapper.containsKey(key)) { continue; } Field declaredField = columnFieldMapper.get(key); if (declaredField == null) { continue; } //數據庫字段值 Object value = entry.getValue(); setFieldValue(instance, declaredField, value); } return instance; }其中 columnFieldMapper 是一個Map<String, Field>。key是表的字段個名稱。value是對應的class的屬性。
下面是 setFieldValue的具體代碼:
boolean setFieldValue(T t, Field field, Object value) { field.setAccessible(true); try { if (value != null) { field.set(t, value); return true; } } catch (IllegalAccessException e) { e.printStackTrace(); } return false; }這樣,就可以將查詢出的結果根據映射關系轉換成為我們需要的class了。
其他的
如果查詢需要添加條件的話,可以使用之前講的 生成條件的工具將條件的sql拼接在這里的sql后面,相應的,where里的參數也要按照順序添加進數組就好了。
相同的,如果要添加 ORDER BY/GROUP BY/LIMIT這些東西的話也是一樣的操作。主要還是要看自己的代碼是怎么設計的了。我自己用的只寫了ORDER BY 和 LIMIT 。可以在我的github上找到。地址在這里:https://github.com/hjx601496320/JdbcPlus 。
生成sql:delete
思路
誒呀, 這個太簡單了。不寫了哦~~~
參照我之前寫的,分析一下,想一想思路,然后每一步要怎么做,一點一點的就寫好了。
~~~
實現
你自己寫咯~~~。
其他的
這一篇寫的真快~~
生成sql:update
最后一部分了,馬上就寫完了。寫東西真的好累啊~~~
思路
更新的語句也比較好做,sql后面的條件因為在之前已經寫了where這一篇,所以這里就只寫sql中where左邊的一部分。現在還是先分析一下 **update **語句:
UPDATE user SET name = ? , id = ? , create_date = ? , age = ? , status = ? WHERE id = ?
可以看到的,大體上就是 UPDATE 表名稱 SET 字段名稱 = ? 這個樣子的。(因為現在不寫WHERE右邊的)
所以具體的思路就是:
-
根據映射關系拼裝sql。
這里可能有一個可以選擇的地方,就是如果某一個屬性的值是null,這時要不要把這個屬性更新為null。
-
拿到要更新的值。
-
執行sql。
實現
-
從映射中拿到所有的屬性。
這一步的代碼就不放了~~~,和前面寫的沒有什么區別。
-
拿到要更新的屬性名稱,和值。
這里我們需要三個參數:
1:用來標示更新的時候是否需要忽略值是null的屬性。 boolean ignoreNull
2:用來保存需要更新的字段的有序集合。 List
updataColumn 3:保存需要更新的字段的值的有序集合。 List
