嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

周梦康 发表于 2016-08-03 1258 次浏览 标签 : Java

免费领取阿里云优惠券 我的直播 - 《PHP 进阶之路》

这个不是详细的教程类博客,没有条理性,仅供个人复习使用。

注解的分类

源码注解:编译成class文件就不存在了。

编译时注解:源码里存在,在class里就不存在了(JDK内置注解就是编译时注解)。

运行时注解:Spring 的注解,就是运行时注解。

JDK内置注解

@Override

@Deprecated

@SuppressWarnings

实战笔记

使用注解来映射表字段名和对象的属性名

import java.lang.annotation.*;

/**
 * Created by zhoumengkang on 16/8/3.
 */
// 是否生成文档
@Documented
// 在运行时生效
@Retention(RetentionPolicy.RUNTIME)
// 适用的位置
@Target({ElementType.FIELD})
public @interface DbFiled {
    String value();
}
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhoumengkang on 16/8/3.
 */
public class Db<A> {

    private Class clazz;

    private Map<String, Field> fieldMap = new HashMap<>();

    public Db(A bean) {
        this.clazz = bean.getClass();
        fieldMapInit();
    }

    /**
     * 数据库中的字段和bean属性值的映射
     * {
     *     数据库字段名               bean 属性名
     *     create_time      :       createTime
     * }
     */
    private void fieldMapInit() {
        Field[] fields = clazz.getDeclaredFields();
    
        for (Field field : fields) {
            if (field.isAnnotationPresent(DbFiled.class)) {
                fieldMap.put(field.getAnnotation(DbFiled.class).value(), field);
            } else {
                fieldMap.put(field.getName(), field);
            }
        }
    }
    
    /**
     * 根据 fieldMap 里字段名和 bean 属性名的对应关系,根据查询字段取出对应的属性名
     * 然后通过反射设置值
     *
     * @param selectFields
     * @param resultSet
     * @return
     */
    @SuppressWarnings("unchecked")
    public A resultSet(String[] selectFields,ResultSet resultSet){
    
        A bean = null;
    
        try{
            bean = (A) Class.forName(clazz.getName()).newInstance();
    
            for (int i = 0; i < selectFields.length; i++) {
                int j = i + 1;
                Field field = fieldMap.get(selectFields[i]);
                field.setAccessible(true);
                Class fieldClass = field.getType();
                if (fieldClass == String.class) {
                    field.set(bean, resultSet.getString(j));
                } else if (fieldClass == int.class || fieldClass == Integer.class) {
                    field.set(bean, resultSet.getInt(j));
                } else if (fieldClass == float.class || fieldClass == Float.class) {
                    field.set(bean, resultSet.getFloat(j));
                } else if (fieldClass == double.class || fieldClass == Double.class) {
                    field.set(bean, resultSet.getDouble(j));
                } else if (fieldClass == long.class || fieldClass == Long.class) {
                    field.set(bean, resultSet.getLong(j));
                } else if (fieldClass == Date.class) {
                    field.set(bean, resultSet.getDate(j));
                }
            }
        } catch (SQLException e | IllegalAccessException | ClassNotFoundException | InstantiationException e) {
            e.printStackTrace();
        }
    
        return bean;
    }
    
    /**
     * 解析查询语句的字段 目前还不支持 * 查询 (也最好不要用)
     *
     * @param sql
     * @return
     */
    private String[] parseSelectFields(String sql) {
        sql = sql.toLowerCase();
    
        String[] fieldArray = sql.substring(sql.indexOf("select") + 6, sql.indexOf("from")).split(",");
        int      length     = fieldArray.length;
        String[] fields     = new String[length];
    
        for (int i = 0; i < length; i++) {
            fields[i] = fieldArray[i].trim().replace("`", "");//`
        }
    
        return fields;
    }
    
    public A get(String sql, Object... params) {
    
        grammarCheck(sql, DMLTypes.SELECT);
        int paramSize = getParameterNum(sql, params);
    
        Connection        conn      = null;
        PreparedStatement statement = null;
        ResultSet         resultSet = null;
    
        try {
            conn = JdbcPool.getReadConnection();
            statement = conn.prepareStatement(sql);
    
            if (paramSize > 0) {
                statement = bindParameters(statement, params);
            }
    
            resultSet = statement.executeQuery();
            if (resultSet.next()){
                String[] selectFields = parseSelectFields(sql);
                return resultSet(selectFields,resultSet);
            }
        } catch (SQLException e) {
            logger.error("sql error", e);
        } finally {
            JdbcPool.release(conn, statement, resultSet);
        }
        return null;
    }
    
    // ... 其他方法    
}

上面的方法中,就将数据库中的字段名和类中的属性吗名的对应关系放在了fieldMap中了。

根据fieldMap里字段名和bean属性名的对应关系,根据查询字段取出对应的属性名.然后通过反射给属性赋值。

完整的可以查看

https://github.com/zhoumengkang/netty-restful-server/blob/master/src/main/java/net/mengkang/nettyrest/mysql/MySelect.java

下面是一个bean

public class User {
    private Long id;
    private String username;
    @DbFiled("register_ts")
    private int ts;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getTs() {
        return ts;
    }

    public void setTs(int ts) {
        this.ts = ts;
    }
}

一个示例操作

Db db = new Db<>(new User());
String sql = "select id,username,register_ts from user where id=?";
return (User) db.get(sql, 1);


嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表