使用自定义注解简单实习orm框架的sql生成

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用自定义注解简单实习orm框架的sql生成相关的知识,希望对你有一定的参考价值。


使用自定义注解简单实习orm框架的sql生成

  • ​​背景​​
  • ​​代码​​
  • ​​我们先把架子搭出来​​
  • ​​自定义注解: table注解​​
  • ​​工具类​​
  • ​​查询条件使用自定义注解实现​​

背景

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;


以上是关于使用自定义注解简单实习orm框架的sql生成的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot自定义校验注解

将 ORM 安装到自定义 PHP5 框架中

Java 注解自定义注解 ( 使用注解实现简单测试框架 )

MyBatis基础

ORM框架-MyBatis使用经验总结

MyBatis配置文件详解