java orm 最好_手把手教你写一个java的orm(五)

生成sql:where

上一篇里我们实现了生成insert的sql,下面要开始实现update,delete,select的sql语句了。但是这些语句有一个比较麻烦的地方是:它们一般后面都会有where条件,因为在执行的时候不能把表里所有的数据都进行操作。

所以这里我们需要先生成条件的sql。大概是这样的:

WHERE id = ? AND name != ? OR age >= ?

where 后面的参数继续用 “?” 代替。值就放在一个有序的集合中就好了。类似上一篇提到的insertColumnValues。

思路

条件都是一个一个组成的,我们可以写一个类用来描述一个条件。

写一个工具类来快速的创建条件。

将多个条件中间用 and 或者 or 组合起来,并在最前方添加 where 就是一个完整的条件。

最后将这个条件转成一个字符串,并用一个集合将条件中的值存起来就好了。

实现

第一步

我们实现第一步,在这之前我们先看一下一个条件是有什么组成的,例如:

1: id = ? AND

2: name != ? OR

3: age >= ?

这里通过观察可以发现,每一个条件都是由一个 字段名称,一个判断,一个占位符 "?"和后面用于连接条件的 AND 或者 OR 所构成。这样我们可以编写一个类用来保存这些信息:

Where.java

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

/**

* where条件 默认使用 and 连接多个条件

*

* @author hjx

*/

public class Where {

protected static final String PLACEHOLDER = "#{COLUMN}";

static final String AND = "AND ";

static final String OR = "OR ";

private String sql;

private String column;

private String connect = AND;

private List values;

/**

* 是否有值(null 也代表有值)

*/

private boolean hasValue;

/**

* @param column 被操作的列

* @param sql 操作的sql

*/

public Where(String column, String sql) {

this.column = column;

this.sql = sql;

this.hasValue = false;

this.values = new ArrayList<>();

}

/**

* @param column 被操作的列

* @param sql 操作的sql

* @param value sql的参数

*/

public Where(String column, String sql, Object value) {

this.sql = sql;

this.column = column;

this.values = new ArrayList<>();

this.values.add(value);

this.hasValue = true;

}

/**

* @param column 被操作的列

* @param sql 操作的sql

* @param values sql的参数

*/

public Where(String column, String sql, Object[] values) {

this.sql = sql;

this.column = column;

this.values = Arrays.asList(values);

this.hasValue = true;

}

public Where or() {

this.connect = OR;

return this;

}

public Where and() {

this.connect = AND;

return this;

}

/**

* 获取本次条件的连接符

*

* @return

*/

public String getConnect() {

return connect;

}

protected String getSql() {

return sql;

}

protected boolean isHasValue() {

return hasValue;

}

protected List getValues() {

return values;

}

public String getColumn() {

return column;

}

}

上面中的常量 PLACEHOLDER 是作为一个占位符使用的,下面会说道。

这样,一个用于保存单个条件的类就写好了,在一个sql中有多个条件的话,只需要用一个ArrayList保存这些条件,并按照一定的条件拼装成sql就好了。

第二步

sql中还有一些比较常用的判断,比如:!= , = , <= , >= 等等,我们在这里可以创建一个工具类来快速的生成Where 这个类,可以这样写:

Wheres.java

import java.util.Arrays;

/**

* 查询条件

* @author hjx

*/

public class Wheres {

public static Where equal(final String columnName, final Object value) {

return new Where(columnName, Where.PLACEHOLDER + " = ? ", value);

}

public static Where notEqual(final String columnName, final Object value) {

return new Where(columnName, Where.PLACEHOLDER + " != ? ", value);

}

public static Where not(final String columnName, final Object value) {

return new Where(columnName, Where.PLACEHOLDER + " <> ? ", value);

}

public static Where isNotNull(final String columnName) {

return new Where(columnName, Where.PLACEHOLDER + " IS NOT NULL ");

}

public static Where isNull(final String columnName) {

return new Where(columnName, Where.PLACEHOLDER + " IS NULL ");

}

public static Where greater(final String columnName, final Object value, final boolean andEquals) {

if (andEquals) {

return new Where(columnName, Where.PLACEHOLDER + " >= ? ", value);

}

return new Where(columnName, Where.PLACEHOLDER + " > ? ", value);

}

public static Where less(final String columnName, final Object value, final boolean andEquals) {

if (andEquals) {

return new Where(columnName, Where.PLACEHOLDER + " <= ? ", value);

}

return new Where(columnName, Where.PLACEHOLDER + " < ? ", value);

}

public static Where like(final String columnName, final Object value) {

return new Where(columnName, Where.PLACEHOLDER + " like ? ", value);

}

public static Where betweenAnd(final String columnName, final Object value1st, final Object value2nd) {

return new Where(columnName, Where.PLACEHOLDER + " between ? and ? ", new Object[]{value1st, value2nd});

}

public static Where in(final String columnName, final Object[] values) {

Object[] sqlVal = values;

if (sqlVal.length == 0) {

sqlVal = new Object[]{null};

}

StringBuffer inSql = new StringBuffer();

inSql.append(Where.PLACEHOLDER);

inSql.append(" IN ( ");

String[] strings = StringUtils.repeat("?", sqlVal.length);

inSql.append(StringUtils.join(Arrays.asList(strings), ", "));

inSql.append(" ) ");

return new Where(columnName, inSql.toString(), sqlVal);

}

}

这里只是简单的列出了一些常用的判断条件,如果有特殊需要的自己再加进去就好了。

关于常量 PLACEHOLDER 是这么一回事:

在生成sql 的时候,我需要做一些字段上的验证。这里在sql中使用一个占位符放进sql中,真正参与条件的字段放在另外一个属性中保存。这样在真正生成sql的时候可以验证条件中的字段在不在表中,如果存在的话将字段和占位符进行替换就好了。并且如果使用的是属性名称的话,也可以根据名称找到对应的表的字段名。

第三步

通过上面的代码,我们可以很方便的创建条件了。现在我们将这些条件组装成我们需要的完整的sql。

注意:这里的代码可能和我的github上的不太一样,因为这里只讲一下思路,具体的怎么将所有的代码组装起来让它成为一个完整的项目,每个人都不一样。所以~~~ 嘿嘿。

现在开始:

我们还是以之前写的User.java为例子

List wheres = Arrays.asList(

Wheres.equal("name", "李叔叔"),

Wheres.notEqual("status", 1),

Wheres.in("age", new Integer[]{1, 2, 3, 4, 5}),

Wheres.greater("age", 20, true)

);

List sqlValue = new ArrayList<>();

StringBuilder sql = new StringBuilder();

if (wheres.size() != 0) {

sql.append("WHERE ");

for (int i = 0; i < wheres.size(); i++) {

Where where = wheres.get(i);

if (i != 0) {

sql.append(where.getConnect());

}

String column = where.getColumn();

String whereSql = where.getSql();

sql.append(

//这里获取真实sql

whereSql.replace(Where.PLACEHOLDER, getColumnName(column))

);

//因为有些条件中的参数可能是有多个

List values = where.getValues();

for (int j = 0; j < values.size(); j++) {

sqlValue.add(values.get(j));

}

}

}

System.out.println(sql.toString());

System.out.println(sqlValue.toString());

这里说明一下:getColumnName(String name) ,这个方法是根据参数获取真正的字段名称的方法。因为这个条件中可能传入的是java属性的名称而不是表的字段名称,需要转换成为真正的表的字段名。这一步也是从之前生成的映射中获取的。顺便还能验证一下表中有没有这个字段。这个方法我就不贴出来了,github上有。

输出结果:

WHERE name = ? AND status != ? AND age IN ( ?, ?, ?, ?, ? ) AND age >= ?

[李叔叔, 1, 1, 2, 3, 4, 5, 20]

这里一个where就写好了,并且也可以拿到条件中的参数了。

剩下的就是后面的单独生成update,delete,select 类型sql的操作了。

我下一篇再写~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值