開始准備生成sql
在上一篇里,我們已經取到了我們在生成sql語句中所需要的信息,這一篇里我們開始根據class來生成我們需要的sql。在這之前我們先確認幾件事情
-
sql里的參數我們使用占位符的形式。
這里用的是jdbc中的PreparedStatement,sql中的參數使用“?”的形式。
大致上是這樣的:
Connection connection = dataSource.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("select * from `user` where `status` = ? ;"); preparedStatement.setObject(1, 0); ResultSet resultSet = preparedStatement.executeQuery();
但是這樣的話我們每次執行都需要手寫這些執行sql的繁瑣的代碼,我在這里選擇使用spring-jdbc中的JdbcTemplte。這樣我就只需要生成sql,然后使用JdbcTemplte里的方法來執行sql就好了。
-
我們只生成單表的增刪改查,不涉及復雜sql。
-
不貼出完整的代碼,以說明思路為主。
畢竟這個是已經寫好的代碼,地址在:https://github.com/hjx601496320/JdbcPlus 。所有代碼可以在這里找到。
分析sql
我們主要解決的是增刪該查的問題,所以我們先寫如何生成一個新增的sql。
我么先觀察一下sql一般來說都有什么構成。現在先放一個例子出來:
-
insert
INSERT INTO user (name, id, create_date, age, mark, status) VALUES (?, ?, ?, ?, ?, ?);
-
delete
DELETE FROM user WHERE id = ?
-
update
UPDATE user SET name = ?, id = ?, create_date = ?, age = ?, status = ? WHERE id = ?
-
select
SELECT name, id, create_date, age, mark, status FROM user WHERE id = ?
通過觀察上面的sql,可以發現其中有一些共性:
- 都有表的名稱。
- 基本上都包含表中的字段名稱。
- 還有參數。
- 以上都是廢話 😉
接下來,就可以按照每種類型的sql來創建sql了。
操作對象
一下所有的對象都是這個User.java
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Table(name = "user")
public class User {
@Column(name = "name")
private String name;
@Id
@Column(name = "id")
private int id;
@Column(name = "age")
private int age;
@Column(name = "mark")
private String mark;
@Column(name = "create_date")
private Date createDate;
@Column(name = "status")
private int status;
// getter setter toString
}
先寫點工具代碼
主要用來操作字符串
import java.util.Collection;
import java.util.Iterator;
/**
* @author hjx
*/
public class StringUtils {
public static final String SPACE = " ";
public static final String BLANK = "";
public static final String COMMA = ", ";
/**
* 重復字符串
*
* @param str
* @param number
* @return
*/
public static String[] repeat(String str, int number) {
Assert.notNull(str);
String[] strings = new String[number];
for (int i = 0; i < number; i++) {
strings[i] = str;
}
return strings;
}
/**
* 組合字符串
*
* @param strings
* @return
*/
public static String append(final Object... strings) {
StringBuilder builder = new StringBuilder();
for (Object s1 : strings) {
if (s1 == null) {
continue;
}
builder.append(s1.toString());
}
return builder.toString();
}
/**
* 組合字符串
*
* @param collection
* @param separator
* @return
*/
public static String join(Collection collection, String separator) {
StringBuffer var2 = new StringBuffer();
for (Iterator var3 = collection.iterator(); var3.hasNext(); var2.append((String) var3.next())) {
if (var2.length() != 0) {
var2.append(separator);
}
}
return var2.toString();
}
}
用來從對象中取值的,使用反射。
/**
* 取值
*
* @param target 要從哪一個對象中取值
* @param field 要取這個對象的那個屬性的值
* @return
*/
public static Object getValue(Object target, Field field) {
//忽略掉private
field.setAccessible(true);
try {
return field.get(target);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
用來給對象設置值的,還是反射。
/**
* 設置值
*
* @param target 要從哪一個對象中取值
* @param field 要取這個對象的那個屬性的值
* @param value 要設置的值
* @return
*/
public static boolean setValue(Object target, Field field, Object value) {
field.setAccessible(true);
try {
field.set(target, value);
return true;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
下面就可以開始創建各種sql了~~~
生成sql:insert
思路
新增的sql還是比較好實現的,我們需要的大致就是:
- 構建一個對象 User。
- 調用新增的方法,將User作為參數傳入方法。
- 通過上一篇的解析結果,拿到所有的字段名稱,與要保存的值。生成sql。
- 通過JdbcTemplate執行sql,插入數據庫。
實現
首先我們要根據User.java拿到所有的表的字段個名稱,和對應的值。就是上一篇寫到的:EntityTableRowMapper
-
拿到字段和class屬性的值
Map<String, Field> columnFieldMapper = entityTableRowMapper.getColumnFieldMapper(); insertColumns = new ArrayList(columnFieldMapper.size()); for (Map.Entry<String, Field> stringFieldEntry : columnFieldMapper.entrySet()) { Field field = stringFieldEntry.getValue(); Object value = EntityUtils.getValue(entity, field); if (value == null) { continue; } insertColumns.add(stringFieldEntry.getKey()); insertColumnValues.add(value); }
這里有兩個變量:
insertColumns:sql中的字段名。
insertColumnValues:sql中的字段對應的值。
-
生成插入的sql:
StringBuilder builder = new StringBuilder(); int size = insertColumns.size(); builder.append("INSERT INTO ").append(getTableName()).append(StringUtils.SPACE); builder.append(StringUtils.append("( ", StringUtils.join(insertColumns, ", "), " ) ")); builder.append("VALUES "); for (int i = 0; i < insertCount; i++) { builder.append("( "); String[] repeat = StringUtils.repeat("?", size); builder.append(StringUtils.join(Arrays.asList(repeat), ", ")); builder.append(" )"); if (i != insertCount - 1) { builder.append(StringUtils.COMMA); } } builder.append(";");
-
生成的結果:
//user User user = new User(); user.setId(10); user.setCreateDate(new Date()); user.setAge(20); user.setMark("ceshi"); user.setName("heiheihei"); //sql INSERT INTO user ( name, id, create_date, age, mark, status ) VALUES ( ?, ?, ?, ?, ?, ? ); //value [heiheihei, 10, Tue Jan 22 16:33:00 CST 2019, 20, ceshi, 0]
-
現在可以拿着生成的sql和值去執行啦~
jdbcTemplate.update(sql, insertColumnValues.toArray());
結束啦,剩下的下一篇寫~~