Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

手把手教你写一个java的orm(四)

何白白 2019-01-22 16:40:00 阅读数:141 评论数:0 点赞数:0 收藏数:0

开始准备生成sql

在上一篇里,我们已经取到了我们在生成sql语句中所需要的信息,这一篇里我们开始根据class来生成我们需要的sql。在这之前我们先确认几件事情

  1. 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就好了。

  2. 我们只生成单表的增删改查,不涉及复杂sql。

  3. 不贴出完整的代码,以说明思路为主。

    毕竟这个是已经写好的代码,地址在:https://github.com/hjx601496320/JdbcPlus 。所有代码可以在这里找到。

分析sql

我们主要解决的是增删该查的问题,所以我们先写如何生成一个新增的sql。

我么先观察一下sql一般来说都有什么构成。现在先放一个例子出来:

  1. insert

    INSERT INTO user (name, id, create_date, age, mark, status)
    VALUES (?, ?, ?, ?, ?, ?);
  2. delete

    DELETE
    FROM user
    WHERE id = ? 
  3. update

    UPDATE user
    SET name = ?,
    id = ?,
    create_date = ?,
    age = ?,
    status = ?
    WHERE id = ? 
  4. select

    SELECT name, id, create_date, age, mark, status
    FROM user
    WHERE id = ?

通过观察上面的sql,可以发现其中有一些共性:

  1. 都有表的名称。
  2. 基本上都包含表中的字段名称。
  3. 还有参数。
  4. 以上都是废话 ;-)

接下来,就可以按照每种类型的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还是比较好实现的,我们需要的大致就是:

  1. 构建一个对象 User。
  2. 调用新增的方法,将User作为参数传入方法。
  3. 通过上一篇的解析结果,拿到所有的字段名称,与要保存的值。生成sql。
  4. 通过JdbcTemplate执行sql,插入数据库。

实现

首先我们要根据User.java拿到所有的表的字段个名称,和对应的值。就是上一篇写到的:EntityTableRowMapper

  1. 拿到字段和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中的字段对应的值。

  2. 生成插入的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(";");
  3. 生成的结果:

    //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]
  4. 现在可以拿着生成的sql和值去执行啦~

    jdbcTemplate.update(sql, insertColumnValues.toArray());
结束啦,剩下的下一篇写~~

版权声明
本文为[何白白]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/hebaibai/p/10304633.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领