使用自定义注解简单实习orm框架的sql生成
背景
orm 框架怎么生成的sql,我们给他一个实体对象如何生成sql,这个大家有没有想过,今天我们使用自定义注解来实现一把
代码
直接上代码了就用一个简单的实体对象吧
@Data
public class User {
private String name;
private String password;
private Integer age;
public User(String name, String password, Integer age) {
this.name = name;
this.password = password;
this.age = age;
}
}
我们先把架子搭出来
public class UserDao {
public void getUser(User user){
//这个地方我们只模仿生成sql即可,有了sql再用jdbc即可
//但是如果生成sql,我们想要的就是 select * from user where name = "" and age = 13
//我们去封装一个获取sql的方法
String createsql = SqlUtil.createsql(user);
System.out.println(createsql);
}
public static void main(String[] args) {
User u = new User();
new UserDao().getUser(u);
}
}
说吧了就是想要一个这样的效果,比较简单,方便大家理解自定义注解的使用
自定义注解: table注解
package com.wfg.annotation;
//自定义注解 表示表
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//表示注解可以加在哪
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
public String value() default "";
}
user实体类增加
@Table(value = “t_user”)
工具类
package com.wfg.dao;
import com.wfg.annotation.Table;
/**
* @author wufagang
* @description
* @date 2021年04月18日 8:33 上午
*/
public class SqlUtil {
//获取一个查询sql
public static String createsql(Object object){
//step1 : 获取运行类型
Class<?> clazz = object.getClass();
//step1 判断是否加了这个注解
StringBuffer sb = new StringBuffer("select * from ");
if(clazz.isAnnotationPresent(Table.class)){
//step2 得到注解
Table annotation = clazz.getAnnotation(Table.class);
String value = annotation.value();
sb.append(value);
}
return sb.toString();
}
}
此时我们一节可以获取
select * from t_user
同理我们可以自定义字段和
这里整理一个工作中条件查询使用的自定义注解,部分敏感代码我会替换的
查询条件使用自定义注解实现
package com.jd.cjg.businessidentity.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Query {
// 基本对象的属性名
String propName() default "";
// 查询方式
Type type() default Type.EQUAL;
/**
* 连接查询的属性名,如User类中的dept
*/
String joinName() default "";
/**
* 默认左连接
*/
Join join() default Join.LEFT;
/**
* 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
*/
String blurry() default "";
enum Type {
// 相等
EQUAL
// 大于等于
, GREATER_THAN
// 小于等于
, LESS_THAN
// 中模糊查询
, INNER_LIKE
// 左模糊查询
, LEFT_LIKE
// 右模糊查询
, RIGHT_LIKE
// 小于
, LESS_THAN_NQ
// 包含
, IN
, NOT_IN
// 不等于
,NOT_EQUAL
// between
,BETWEEN
// 不为空
,NOT_NULL
// 为空
,IS_NULL
}
/**
* 适用于简单连接查询,复杂的请自定义该注解,或者使用sql查询
*/
enum Join {
LEFT, RIGHT, INNER
}
}
query注解工具类
@Slf4j
public class QueryHelper {
public static <Q> List<Example.Criteria> createCriteria(Example example, Q condition) {
if(condition == null){
return example.getOredCriteria();
}
Example.Criteria criteria = example.createCriteria();
List<Example.Criteria> list = new ArrayList<>();
try {
List<Field> fields = getAllFields(condition.getClass(), new ArrayList<>());
for (Field field : fields) {
boolean accessible = field.isAccessible();
// 设置对象的访问权限,保证对private的属性的访
field.setAccessible(true);
Query q = field.getAnnotation(Query.class);
if (q != null) {
String propName = q.propName();
String joinName = q.joinName();
String blurry = q.blurry();
String attributeName = isBlank(propName) ? field.getName() : propName;
Class<?> fieldType = field.getType();
Object val = field.get(condition);
if (Objects.isNull(val) || "".equals(val)) {
continue;
}
Join join = null;
switch (q.type()) {
case EQUAL:
list.add(criteria.andEqualTo(attributeName, val));
break;
case GREATER_THAN:
list.add(criteria.andGreaterThanOrEqualTo(attributeName, val));
break;
case LESS_THAN:
list.add(criteria.andLessThanOrEqualTo(attributeName, val));
break;
case LESS_THAN_NQ:
list.add(criteria.andLessThan(attributeName, val));
break;
case INNER_LIKE:
list.add(criteria.andLike(attributeName, "%" + val.toString() + "%"));
break;
case LEFT_LIKE:
list.add(criteria.andLike(attributeName, "%" + val.toString()));
break;
case RIGHT_LIKE:
list.add(criteria.andLike(attributeName, val.toString() + "%"));
break;
case IN:
if (CollectionUtils.isNotEmpty((Collection<Object>)val)) {
list.add(criteria.andIn(attributeName, (Collection<Object>)val));
}
break;
case NOT_IN:
if (CollectionUtils.isNotEmpty((Collection<Object>)val)) {
list.add(criteria.andNotIn(attributeName, (Collection<Object>)val));
}
break;
case NOT_EQUAL:
list.add(criteria.andNotEqualTo(attributeName, val));
break;
case NOT_NULL:
list.add(criteria.andIsNotNull(attributeName));
break;
case IS_NULL:
list.add(criteria.andIsNull(attributeName));
break;
case BETWEEN:
List<Object> between = new ArrayList<>((List<Object>)val);
list.add(criteria.andBetween(attributeName, between.get(0), between.get(1)));
break;
default: break;
}
}
field.setAccessible(accessible);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return list;
}
private static boolean isBlank(final CharSequence cs) {
int strLen;
if (cs == null || (strLen = cs.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
}
public static List<Field> getAllFields(Class clazz, List<Field> fields) {
if (clazz != null) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
getAllFields(clazz.getSuperclass(), fields);
}
return fields;
}
}