ORM框架,反射,泛型,注解,CRUD实现

注解与反射:

注:内容介绍_哔哩哔哩_bilibili

注解就是对代码的注释,反射就是java理解注解的方式。反射可以在类运行时获取类相关属性,方法等。

声明注解:@interface

元注解:@Target @Retention @Document和@Inherited

定义一个注解

/**
 * RetentionPolicy:
 * SOURCE:在代码中,不会在class中
 * CLASS: 编译在class,jvm会忽略
 * RUNTTIME: 运行时生效
 */
@Target(ElementType.METHOD)   //可以表明注解用在类/方法/字段上
@Retention(RetentionPolicy.RUNTIME)  //保留策略
public @interface MyAnno {

    //默认的方法,会带到jvm中,会在反射中获得这些值
    String value();
}

定义一个反射类

@TableName(value = "类上注解")
public class User {

//    @MyAnno(value = "通过反射获取默认值")
    @TableField(value = "变量注解")
    private String userId;

    @MyAnno(value = "通过反射获取方法注解")
    private void work(String userId){
        System.out.println("");
    }
}

 获取相关属性

public class ReflecDemo {
    public static void main(String[] args) {
        TableName tableName = User.class.getAnnotation(TableName.class);  //通过反射获取对象
        System.out.println(tableName.value());

        Field[] declaredFields = User.class.getDeclaredFields();  //获取对象变量
        for (Field field : declaredFields) {
            TableField tableField = field.getAnnotation(TableField.class);
            if(null != tableField){
                System.out.println(field.getName() + "   -   " + tableField.value());
            }
        }

        Method[] declaredMethods = User.class.getDeclaredMethods();
        for (Method method : declaredMethods) {
            MyAnno myAnno = method.getAnnotation(MyAnno.class);
            if(null != myAnno){
                System.out.println(method.getName() + " - " + myAnno.value());  //获取方法上注解
            }
        }
    }
}

实现一个ORM框架

目标:通过一个包含自定义注解的POJO类,来描述POJO与数据库中表的对应关系,然后由框架统一完成对数据库中表的CRUD操作。

代码:许宇 (xuyu294636185) - Gitee.com

步骤:

1.定义实体与注解,从实体中解析出CRUD对应的SQL语句

/**
 * 定义table注解:指明orderInfo实体对应数据库的那张表
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    public String tableName();  //对应表名
    public String orderBy() default "";  //排序字段,可为空
    public String order() default "";  //升降序
}
/**
 * 表中字段对应关系
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableColumn {
    public String dbColumn();  //对应数据库列
    public String isPK() default "";  //是否主键
    public String dbColumnType() default "";  //数据库字段类型
}
@Table(tableName = "order_info",orderBy = "order_date",order = "desc")
public class OrderInfo {

    @TableColumn(dbColumn = "order_id",isPK = "true")
    private int orderId;
    @TableColumn(dbColumn = "client_name")
    private String clientName;
    @TableColumn(dbColumn = "produce_name")
    private String productName;
    @TableColumn(dbColumn = "order_date")
    private Date orderDate;

    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    public String getClientName() {
        return clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Date getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }
}
/**
 * 对OrderInfo对象生成sql语句
 */
public class SQLProvider {

    //select xxx,xxx from table where xxx = 'xxx' and xxx = 'xxx' order by xxx desc|asc
    public String genQuerySQL(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuffer sql = new StringBuffer("select ");
        StringBuffer paramSql = new StringBuffer();
        StringBuffer whereSql = new StringBuffer(" where 1=1 ");

        Class<? extends OrderInfo> clazz = orderInfo.getClass();
        Table table = clazz.getAnnotation(Table.class);
        if (table == null) {
            System.out.println("no table");
        }
        //拿到表名和排序字段和顺序
        String tableName = table.tableName();
        String order = table.order();
        String orderBy = table.orderBy();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (tableColumn != null) {
                paramSql.append(tableColumn.dbColumn()).append(",");
            }
            String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
            if(null==fieldValue || StringUtils.isEmpty(field.toString())){
                continue;
            }
            fieldValue = getColumnType(field, fieldValue);
            whereSql.append(" and ").append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
        }

        sql.append(paramSql.substring(0, paramSql.length() - 1)).append(" from ").append(tableName).append(whereSql);
        if (!StringUtils.isEmpty(orderBy)) {
            sql.append(" order by ").append(orderBy);
            if (!StringUtils.isEmpty(order)) {
                sql.append(" " + order);
            }
        }
        return sql.toString();
    }

    //update table set tableColumn = 'xxx',tableColumn = 'xxx' where pk = ?
    public String genUpdateSQL(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuffer sql = new StringBuffer("update ");
        StringBuffer setSql = new StringBuffer(" set ");
        StringBuffer whereSql = new StringBuffer();
        StringBuffer columnSql = new StringBuffer();

        Class<? extends OrderInfo> clazz = orderInfo.getClass();
        Table table = clazz.getAnnotation(Table.class);
        if (null == table) {
            System.out.println("未配置表名");
        }
        String tableName = table.tableName();

        //遍历tableColumn属性
        for (Field field : clazz.getDeclaredFields()) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (tableColumn == null) {
                continue;
            }
            if (StringUtils.isEmpty(tableColumn.isPK())) {
                String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getField();
                if (null == fieldValue) {
                    continue;
                }
                fieldValue = getColumnType(field, fieldValue);
                columnSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue).append(" , ");
            }
        }
        setSql.append(columnSql.substring(0, columnSql.length() - 2));
        for (Field field : clazz.getDeclaredFields()) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            boolean ss = StringUtils.isEmpty(whereSql.toString());
            if (!StringUtils.isEmpty(tableColumn.isPK()) && ss) {
                String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
                if (null == fieldValue || StringUtils.isEmpty(field.toString())) {
                    continue;
                }
                fieldValue = getColumnType(field, fieldValue);
                whereSql.append(" where ");
                whereSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
            }
            if (StringUtils.isEmpty(whereSql.toString())) {
                System.out.println("未设置主键,无法修改");
            }
        }
        sql.append(tableName);
        sql.append(setSql);
        sql.append(whereSql);
        return sql.toString();
    }

    //delete from table where pk = ?
    public String genDeleteSQL(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuffer sql = new StringBuffer("delete from ");
        StringBuffer where = new StringBuffer();

        //找到表名
        Class<? extends OrderInfo> clazz = orderInfo.getClass();  //获取类对象
        Table tableAnno = clazz.getAnnotation(Table.class);  //反射获取类属性
        String tableName = tableAnno.tableName();  //拿到表名
        if (null == tableAnno) {
            System.out.println("未配置table注解");
        }

        //找到列名
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (null == tableColumn) {
                continue;
            }
            if (!StringUtils.isEmpty(tableColumn.isPK()) && StringUtils.isEmpty(where.toString())) {
                //通过反射找到get方法获取orderid值
                String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
                if (null == fieldValue) {
                    System.out.println("未设置主键,无法删除");
                    continue;
                }
                fieldValue = getColumnType(field, fieldValue);
                where.append(" WHERE ");
                where.append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
            }
            //没有找到主键
            if (StringUtils.isEmpty(where.toString())) {
                System.out.println("未设置主键,无法删除");
            }
        }

        //拼接sql
        sql.append(tableName).append(where);
        return sql.toString();
    }

    public String genUpdateSQL2(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuffer sql = new StringBuffer("update ");
        StringBuffer setSql = new StringBuffer(" set ");
        StringBuffer whereSql = new StringBuffer();

        Class<? extends OrderInfo> clazz = orderInfo.getClass();
        Table table = clazz.getAnnotation(Table.class);
        if (table == null) {
            System.out.println("table null");
        }
        String tableName = table.tableName();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (tableColumn == null) {
                continue;
            }
            //通过反射找到get方法获取orderid值
            String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
            if (null != fieldValue && !StringUtils.isEmpty(fieldValue.toString()) && StringUtils.isEmpty(tableColumn.isPK())) {
                setSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue).append(",");
            }

            if (!StringUtils.isEmpty(tableColumn.isPK()) && StringUtils.isEmpty(whereSql.toString())) {
                if (null == fieldValue) {
                    System.out.println("pk is null");
                }
                fieldValue = getColumnType(field, fieldValue);
                whereSql.append(" WHERE ");
                whereSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
            }
        }
        if (setSql.length() <= 5) {
            System.out.println("no column update");
        }
        if (StringUtils.isEmpty(whereSql.toString())) {
            System.out.println("pk is null");
        }

        sql.append(tableName).append(setSql.substring(0, setSql.length() - 1)).append(whereSql);
        return sql.toString();
    }

    private Object getColumnType(Field field, Object fieldValue) {
        //参数类型转换
        if (field.getType() == String.class) {
            fieldValue = "'" + fieldValue + "'";
        } else if (field.getType() == int.class || field.getType() == Integer.class) {
            //...各种类型转换
        }
        return fieldValue;
    }
}
public class ReflectTest {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        //解析出orderInfo对应的CRUD操作的sql语句
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderId(10001);
        orderInfo.setClientName("客户1");
        orderInfo.setProductName("商品1");

        SQLProvider sqlProvider = new SQLProvider();
        System.out.println("增 :" + sqlProvider.genUpdateSQL2(orderInfo));
        System.out.println("查 :" + sqlProvider.genQuerySQL(orderInfo));
        System.out.println("删 :" + sqlProvider.genDeleteSQL(orderInfo));
    }
}

 遗留的问题:

①-传入参数是OederInfo,过于具体

②-异常没有处理

③-参数类型处理没有抽象出来

2.封装成通用的Service

/**
 * 单例数据库链接
 */
public class DBUtil {

    private volatile static Connection connection;

    public static Connection getConnection(){
        if(null == connection){
            synchronized (DBUtil.class){
                if(null == connection){
                    try {
                        Class.forName("com.mysql.cj.jdbc.Driver");
                        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root");
                    }catch (ClassNotFoundException e){
                        e.printStackTrace();
                    }catch (SQLException ex){
                        ex.printStackTrace();
                    }
                }
            }
        }
        return connection;
    }
}
/**
 * 统一的增删改查
 */
public interface BaseService<T> {

    //查
    List<T> queryData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException, InstantiationException;

    //改
    int updateData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException;

    //删
    int deleteData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException;
}
public class BaseServiceImpl<T> implements BaseService<T> {

    private Connection connection = DBUtil.getConnection();

    private GenSQLProvider genSQLProvider = new GenSQLProvider();

    //查询后结果需要通过反射把值设置进去
    public List<T> queryData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException, InstantiationException {
        ArrayList<T> result = new ArrayList<T>();

        //拿到泛型的类类型,不要new对象获取,太low了,用反射
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        Class<T> repoClazz = (Class<T>)type.getActualTypeArguments()[0];

        String sql = genSQLProvider.genQuerySQL(obj);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        while(resultSet.next()){
            //拿到泛型的类类型,不要new对象获取,太low了,用反射
            Object instance = repoClazz.newInstance();
            Field[] fields = repoClazz.getDeclaredFields();
            for (Field field : fields) {
                TableColumn tableColumn = field.getAnnotation(TableColumn.class);
                String columnKey;
                //扩展:没有注解也给映射
                Object fieldRes;
                if(null!= tableColumn){
                    columnKey = tableColumn.dbColumn();
                }else {
                    columnKey = field.getName();  //没有则用字段的名字做列
                }
                try {
                    fieldRes = resultSet.getObject(columnKey, field.getType());
                }catch (SQLException e){
                    continue;
                }
                String setterName = "set" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
                repoClazz.getMethod(setterName,field.getType()).invoke(instance,fieldRes);  //相当于instance.setxxx(fieldRes);
            }
            result.add((T)instance);
        }
        return result;
    }

    public int updateData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
        String sql = genSQLProvider.genUpdateSQL2(obj);
        Statement statement = connection.createStatement();
        return statement.executeUpdate(sql);
    }

    public int deleteData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
        String sql = genSQLProvider.genDeleteSQL(obj);
        Statement statement = connection.createStatement();
        return statement.executeUpdate(sql);
    }
}
/**
 * 对OrderInfo对象生成sql语句
 */
public class GenSQLProvider {

    //select xxx,xxx from table where xxx = 'xxx' and xxx = 'xxx' order by xxx desc|asc
    public String genQuerySQL(Object obj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuffer sql = new StringBuffer("select ");
        StringBuffer paramSql = new StringBuffer();
        StringBuffer whereSql = new StringBuffer(" where 1=1 ");

        Class<?> clazz = obj.getClass();
        Table table = clazz.getAnnotation(Table.class);
        if (table == null) {
            System.out.println("no table");
        }
        //拿到表名和排序字段和顺序
        String tableName = table.tableName();
        String order = table.order();
        String orderBy = table.orderBy();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (tableColumn != null) {
                paramSql.append(tableColumn.dbColumn()).append(",");
            }
            String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            Object fieldValue = clazz.getMethod(getterName).invoke(obj);//相当于orderInfo.getOrderId();
            if(null==fieldValue || StringUtils.isEmpty(field.toString())){
                continue;
            }
            fieldValue = getColumnType(field, fieldValue);
            whereSql.append(" and ").append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
        }

        sql.append(paramSql.substring(0, paramSql.length() - 1)).append(" from ").append(tableName).append(whereSql);
        if (!StringUtils.isEmpty(orderBy)) {
            sql.append(" order by ").append(orderBy);
            if (!StringUtils.isEmpty(order)) {
                sql.append(" " + order);
            }
        }
        return sql.toString();
    }
    private Object getColumnType(Field field, Object fieldValue) {
        //参数类型转换
        if (field.getType() == String.class) {
            fieldValue = "'" + fieldValue + "'";
        } else if (field.getType() == int.class || field.getType() == Integer.class) {
            //...各种类型转换
        }
        return fieldValue;
    }
}

遗留问题:

①异常处理

②数据库链接参数配置项 --整合MyBatis,主要是集成参数类型转换功能。

2.2整合MyBatis

复写Service实现

/**
 * 传入的Bean对象
 * 不创建对象而使用HasHMap传参是因为会有分页需求,获取版本号之类的
 */
@Component
public class MBBaseServiceImpl<T> implements BaseService<T> {

    @Autowired
    BaseMapper baseMapper;
    //TODO:https://www.bilibili.com/video/BV1hd4y1d788?p=14&spm_id_from=pageDriver&vd_source=85a097599612a3ab01f6d380f0d6b0ef

    @Override
    public List<T> queryData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException, InstantiationException {
        ArrayList<T> result = new ArrayList<>();

        //拿到要操作Bean对象的类型,repoClazz代表T的具体类型(OrderInfo.class)
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        Class<?> repoClazz = (Class<?>) type.getActualTypeArguments()[0];

        //具体参数的类型
        Class<?> objClazz = obj.getClass();

        Map<String, Object> paramMap = new HashMap<>();
        Field[] fields = objClazz.getDeclaredFields();
        for (Field field : fields) {
            String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            Object fieldValue = obj.getClass().getMethod(getterName).invoke(obj);
            if (null != fieldValue) {
                paramMap.put(field.getName(), fieldValue);
            }
        }
        List<Map<String, Object>> queryData = baseMapper.selectData(paramMap, repoClazz);
        //通过反射来做封装,将Map封装成T实例
        for (Map<String, Object> data : queryData) {
            Object instance = repoClazz.newInstance();
            Field[] fields2 = repoClazz.getDeclaredFields();
            for (Field field2 : fields2) {
                TableColumn tableColumn = field2.getAnnotation(TableColumn.class);
                String columnKey;
                Object fieldsRes;
                if (null != tableColumn) {
                    columnKey = tableColumn.dbColumn();
                } else {
                    columnKey = field2.getName();
                }
                //TODO 要异常处理
                fieldsRes = data.get(columnKey);

                String setterName = "set" + field2.getName().substring(0, 1) + field2.getName().substring(1);
                repoClazz.getMethod(setterName, field2.getType()).invoke(instance, (Integer)fieldsRes);
            }
            result.add((T) instance);
        }
        return result;
    }

    @Override
    public int updateData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
        //拿到要操作Bean对象的类型,repoClazz代表T的具体类型(OrderInfo.class)
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        Class<T> repoClazz = (Class<T>) type.getActualTypeArguments()[0];

        //具体参数的类型
        Class<?> objClazz = obj.getClass();

        Map<String, Object> param = new HashMap<>();
        Field[] fields = objClazz.getDeclaredFields();
        for (Field field : fields) {
            Object fieldValue = ReflectUtil.getValue(obj, field);
            if (null != fieldValue) {
                param.put(field.getName(), fieldValue);
            }
        }
        return baseMapper.updateData(param, repoClazz);
    }

    @Override
    public int deleteData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        Class<T> repoClazz = (Class<T>) type.getActualTypeArguments()[0];

        Class<?> objClazz = obj.getClass();

        Map<String, Object> param = new HashMap<>();
        Field[] fields = objClazz.getDeclaredFields();
        for (Field field : fields) {
            Object fieldValue = ReflectUtil.getValue(obj, field);
            if (null != fieldValue) {
                param.put(field.getName(), fieldValue);
            }
        }
        int i = baseMapper.deleteData(param, repoClazz);
        return i;
    }
}
public interface BaseMapper {

    /**
     * @UpdateProvider:动态生成sql,不用在xml中写。type:指定生成的类。method:指定那个方法生成的
     * @param param:传入参数
     * @param repo:操作对象
     * @return
     */
    @UpdateProvider(type = MySqlProvider.class, method = "genUpdateSql")
    public Integer updateData(@Param("requestData") Map<String, Object> param, @Param("repoClass") Class<?> repo);

    @DeleteProvider(type = MySqlProvider.class, method = "genDeleteSql")
    public Integer deleteData(@Param("requestData") Map<String, Object> param, @Param("repoClass") Class<?> repo);

    @SelectProvider(type = MySqlProvider.class, method = "genSelectSql")
    public List<Map<String, Object>> selectData(@Param("requestData") Map<String, Object> param, @Param("repoClass") Class<?> repo);
}
public class MySqlProvider {

    public String genUpdateSql(Map<String, Object> param) {
        Map<String, Object> paramMap = (Map<String, Object>) param.get("requestData");
        Class<?> repoClass = (Class<?>) param.get("repoClass");

        Table table = repoClass.getAnnotation(Table.class);
        String tableName = table.tableName();

        //update table set col1 = #{requestData.attr1},col2=#{requestData.attr2} where orderId = #{request.orderId}
        SQL sql = new SQL();
        Field[] fields = repoClass.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (null == tableColumn) {
                continue;
            }
            if (paramMap.containsKey(field.getName()) && StringUtils.isEmpty(tableColumn.isPK())) {
                sql.SET(tableColumn.dbColumn() + "= #{requestData." + field.getName() + "}");
            }
            if (!StringUtils.isEmpty(tableColumn.isPK())) {
                sql.WHERE(tableColumn.dbColumn() + " = #{requestData." + field.getName() + "}");
                continue;
            }
        }
        sql.UPDATE(tableName);
        System.out.println(sql.toString());
        return sql.toString();
    }

    public String genDeleteSql(Map<String, Object> param) {
        Map<String, Object> paramMap = (Map<String, Object>) param.get("requestData");
        Class<?> repoClass = (Class<?>) param.get("repoClass");

        Table table = repoClass.getAnnotation(Table.class);
        String tableName = table.tableName();

        //delete from order_info where orderId = #{requestData.orderId}
        SQL sql = new SQL();
        Field[] fields = repoClass.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (null == tableColumn) {
                continue;
            }
            if (!StringUtils.isEmpty(tableColumn.isPK())) {
                sql.WHERE(tableColumn.dbColumn() + " = #{requestData." + field.getName() + "}");
                break;
            }
        }
        sql.DELETE_FROM(tableName);
        System.out.println(sql.toString());
        return sql.toString();
    }

    public String genSelectSql(Map<String, Object> param) {
        Map<String, Object> paramMap = (Map<String, Object>) param.get("requestData");
        Class<?> repoClass = (Class<?>) param.get("repoClass");

        Table table = repoClass.getAnnotation(Table.class);
        String tableName = table.tableName();


        //select ***,*** from order_info where xxx = #{xxx} and xxx = #{xxx} order by xxx desc|asc
        SQL sql = new SQL();
        Field[] fields = repoClass.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (null == tableColumn) {
                continue;
            }
            sql.SELECT(tableColumn.dbColumn());
            if (paramMap.containsKey(field.getName())) {
                sql.WHERE(tableColumn.dbColumn() + " = #{requestData." + field.getName() + "}");
            }
        }
        sql.FROM(tableName);
        if (!StringUtils.isEmpty(table.orderBy())) {
            sql.ORDER_BY(table.orderBy());
            if (!StringUtils.isEmpty(table.order())) {
                //添加排序顺序
            }
        }
        System.out.println(sql.toString());
        return sql.toString();
    }
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class AnnoDemoTest {
    @Autowired
    OrderInfoService orderInfoService;

    @Test
    public void queryData() throws Exception {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderId(10003);
        orderInfo.setClientName("xuyu");

//        int i = orderInfoService.deleteData(orderInfo);
//        System.out.println(i);

//        int j = orderInfoService.updateData(orderInfo);
//        System.out.println(j);

        List<OrderInfo> orderInfos = orderInfoService.queryData(orderInfo);
        for (OrderInfo info : orderInfos) {
            System.out.println(info);
        }
    }
}

3.自动生成

POJO属性类型有要求,必须与JDBC的返回结果一致。实现将采用自动生成的方式来生成POJO对象。

1.怎么拿到数据库的表结构?(通过JDBC连接获取)

/**
 * 通过JDBC连接获取数据库表结构
 */
public class JDBCTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Properties properties = new Properties();
        properties.put("user", "root");
        properties.put("password", "root");
        properties.put("userInformationSchema", "true"); //加上这个参数就可以从jdbc连接中获取我们想要的结果
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai",
                properties);
        DatabaseMetaData meta = connection.getMetaData();
        System.out.println("==================映射表结构============");
        ResultSet tables = meta.getTables("test", "%", "order_info", new String[]{"TABLE"});  //拿到对应的表;参数:库名,全匹配,表名
        while (tables.next()) {
            ResultSetMetaData metaData = tables.getMetaData();
            String table_name = tables.getString("TABLE_NAME");  //拿到表名
            String remarks = tables.getString("REMARKS");  //拿到备注
            System.out.println("Number for Column:" + metaData.getColumnCount());  //拿到对应列
            for (int i = 1; i < metaData.getColumnCount(); i++) {
                int metaType = metaData.getColumnType(i);
                String metaName = metaData.getColumnName(i);
            }
        }
        System.out.println("==================映射列结构============");
        ResultSet columns = meta.getColumns("test", "%", "order_info", "%");//拿到对应列,参数,同上 + 列的全匹配
        while (columns.next()) {
            String column_name = columns.getString("COLUMN_NAME");//列名
            String type_name = columns.getString("TYPE_NAME");//类型
            int column_size = columns.getInt("COLUMN_SIZE");//列大小
            int decimal_digits = columns.getInt("DECIMAL_DIGITS");//小数点后位数
            int nullable = columns.getInt("NULLABLE");//是否为空
            String remarks = columns.getString("REMARKS");//注解
            System.out.println(column_name + " " + type_name + " " + column_size + " " + decimal_digits + " " + nullable + " " + remarks);
        }
        System.out.println("==================映射主键信息============");
        ResultSet primaryKeys = meta.getPrimaryKeys("test", "%", "order_info");
        while (primaryKeys.next()){
            ResultSetMetaData metaData = primaryKeys.getMetaData();
            int columnCount = metaData.getColumnCount();
            for (int i = 1; i < columnCount; i++) {
                System.out.println(metaData.getColumnName(i) + " " + primaryKeys.getString(metaData.getColumnName(i)));
            }
        }
    }
}

2.怎么生成POJO?(①使用StringBuffer拼凑完成的java代码通过流方式实现-MyBatis实现,②freemarker模板引擎)

https://gitee.com/xuyu294636185/AnnoDemo.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值