手把手教你写一个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());
- 手把手教你写一个java的orm(二)
- 手把手教你写一个java的orm(三)
- 开源组件:(4)用元数据和BeanUtils写一个简单的ORM映射BaseDAO.java
- 手把手教你写一个ORM(二)
- 手把手教你写一个Java在线聊天系统
- sql2java:一个古老但稳定的轻量级的ORM工具的使用说明
- [JAVA]打造一个缩水版的ORM映射(mih)-- beta
- Java面试集锦:面试官只问一个问题,30几人集体懵圈
- 一个高难度的 Java 3D 智力游戏,立方四子棋
- 如何实现用Java编写程序,设计一个模拟电梯运行的类
- JAVA高效学习方法的陈词滥调,给机会一个机会
- 如何部署一个java项目成web项目
- 一个Java程序员应该掌握的10项技能
- 请用Java设计一个Least Recently Used (LRU) 缓存
- Java练习题-输入一个字符串,输出该字符串中字符的所有组合(二)
- java 如何判断一个字符串是数字
- 利用java实现的一个发送手机短信的小例子
- Java中堆内存和栈内存_在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)。修改栈指针就可以把栈中的内容销毁.这样最快
- 用java写一个双向链表
- java程序调用hive查询的一个异常