手把手教你写一个java的orm(四)
开始准备生成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());
结束啦,剩下的下一篇写~~
上一篇: 从零单排学Redis【铂金一】
下一篇: 图片二进制转换与存入数据库相关