自己实现简单对象关系库之缓存类SQLField,SQLClass,SQLCache

上文已经谈到对象关系库需要对操作中间产生的数据进行缓存以提升性能

我们需要对通过反射获取的属性进行缓存
我们需要对属性拼装成的SQL语句进行缓存

综上,我们可以设计出SQLClass作为Class的缓存类保存反射的结果,SQLField作为Field的缓存类保存反射的结果

对于Person类有一个SQLClass<Person> sqlClass=new SQLClass(Person.class)作为其缓存类,缓存类中包含Person所有数据库相关的属性值

public class SQLField{
    private Field field;
    private Column column;
    //省略getter

    //返回SQLField对应的数据库列名称
    public String getName(){
        //如果Column额外设置了名字,则返回设置的名字,否则返回field变量的名字
        if(column.name().length()>0)return column.name();
        return field.getName();
    }


    //遍历类所有的SQLField
    public static void mapSQLField(Class clazz,SQLConsumer<SQLField> consumer){
        if (!clazz.getSuperclass().equals(Object.class)) {
           mapSQLField(clazz.getSuperclass(), mapper);//先访问父类的属性
        }
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
           field.setAccessible(true);
           if (field.isAnnotationPresent(Column.class)) {
               Column column = field.getAnnotation(Column.class);
               mapper.accept(new SQLField<T>(field, column));
           }
        }
    }
}
public class SQLClass<T>{
    private Class<T> clazz;
    private List<SQLField> fields=new LinkedList<>();//保存此类所有Field缓存
    private SQLField primaryKey;
    private String tableName;

    private SQLClass(Class<T> clazz){this.clazz=clazz;}

    public static <T> SQLClass<T> build(Clazz<T> clazz)throws SQLException{
        SQLClass<T> sqlClass=new SQLClass(clazz);
        sqlClass.init();
        return sqlClass();
    }

    //初始化缓存类
    private void init() throws SQLException{
        //获取数据库表名
        if(!clazz.isAnnotationPresent(Table.class))
            throw new SQLException(clazz+"类没有配置表名");
        Table table=clazz.getAnnotation(Table.class);
        this.tableName=table.value();
        //获取数据库对应的所有属性值字段
        SQLField.mapSQLField(clazz,sqlField->{
                fields.add(sqlField);
                if(sqlField.getColumn().isPrimaryKey()){
                    primaryKey=sqlField;
                }
            });
        if(primaryKey==null)throw new SQLException(clazz+"类没有配置主键");
    }

    private String selectSQL;//查询SQL语句的缓存
    private Object selectLock=new Object();
    //返回查询的SQL语句
    public String selectSQL(){
        if(selectSQL==null)
            synchronized(selectLock){
                if(selectSQL==null){
                    selectSQL=initSelectSQL();
                }
            }
        }
        return selectSQL;
    }
    //初始化查询的SQL语句
    private String initSelectSQL(){
        //将每个字段的名字拼接到一起
        StringJoiner joiner=new StringJoiner(",");
        for(SQLField sqlField:fields){
            joiner.add(sqlField.getName());
        }
        StringBuilder builder=new StringBuilder();
        builder.append("SELECT ")
                .append(joiner.toString())
                .append(" FROM ")
                .append(tableName)
                .append(";");
        return builder.toString();
    }

    //上面我已经演示了如何获取查询的SQL语句,后面的增加,删除,更改的SQL语句限于篇幅已经省略

    //把一行ResultSet转化成一个对象实例
    public void toBean(ResultSet rs){
        T t=t.newInstance();
        for(SQLField sqlField:fields){
            sqlField.set(t,rs.get(sqlField.getName());
        }
        return t;
    }
}

现在我们已经知道了如何构建SQLClass作为反射结果和SQL语句的缓存,现在我们还需要一个类作为SQLClass的缓存

public class SQLCache{
    //用来缓存SQLClass的容器
    private ConcurrentHashMap<Class, SQLClass> map = new ConcurrentHashMap<>();
    //获取clazz对应的SQLClass
    public <T> SQLClass<T> getSQLClass(Class<T> clazz) throws SQLException {
        SQLClass<T> sqlClass = map.get(clazz);
        if (sqlClass == null) {
            SQLClass<T> tempSqlClass = SQLClass.build(clazz);
            map.putIfAbsent(clazz, tempSqlClass);
            sqlClass = map.get(clazz);
        }
        return sqlClass;
    }
}

既然我们已经了缓存类,我们的简单对象关系库已经实现了大半部分。
接下来我们考虑的如何使用这些缓存类实现对象关系库

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值