JAVA反射编写简单数据层封装框架

这个demo只是很简单对实体和数据层之间的交互做了封装,没有考虑复杂的情况有很多方法只是支持最原始的单表,不支持级联查询。

思路:

         数据库-》实体:数据库查询结果转化为MAP,使用反射获取实体对应的数据库字段名,通过MAP拼接数据,使用JSON转化为实体。

        实体-》数据库:反射获取实体数据库字段和表名,拼接SQL。

简单执行效果:

实体:

package com.mvc.eitity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Table(name = "userInfo")
public class User {
    @Id
    @Column(name = "id")
   private final int id;
    @Column(name = "name")
//    @Size(min = 2,max = 6,message = "名称不符合要求")
   private String name;
    @Column(name = "age")
//    @Size(min = 1,max = 3,message = "年龄不符合要求")
    @NotNull(message = "年龄不能空")
   private String age;
    @Column(name = "pwd")
    private String passWord;

    public User(int id,String name,String age,String pwd){
        this.id = id;
        this.name = name;
        this.age = age;
        this.passWord = pwd;
    }
    public User(){
        this(0,null,null,null);
    }
    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    @Override
    public String toString() {
        return "********id : " + getId() + "***Name :" + getName() + "******* age : " + age;
    }
}

业务层:

package com.mvc.service.impl;

import com.mvc.dao.UserDao;
import com.mvc.eitity.User;
import com.mvc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public User queryUserById(String userId) {
        StringBuilder sql = new StringBuilder("select * from userinfo where id =" + userId);
        try{
            return userDao.execQuerySQLForEntity(User.class, sql.toString());
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<User> queryUserList(User user) {
        StringBuilder sql = new StringBuilder("select * from userinfo ");
        try{
            return userDao.execQuerySQLForEntityList(User.class, sql.toString());
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void saveUser(User user) {
        try {
            userDao.saveUser(user);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

数据层:

package com.mvc.dao;

import com.mvc.eitity.User;
import com.mvc.utils.DaoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.web.context.ContextLoader;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

@Repository
public class UserDao{
    @Autowired
   private JdbcTemplate jdbcTemplate;

    private JdbcTemplate getJdbcTemplate(){
        return jdbcTemplate;
    }

    /**
     * 查询实体集合
     * @param tClass 实体类
     * @param sql 执行SQL
     * @param params SQL参数
     * @param <T>
     * @return
     */
    public <T> List<T> execQuerySQLForEntityList(Class<T> tClass,String sql,String ... params) throws InstantiationException, IllegalAccessException {
        List<Map<String, Object>> maps = getJdbcTemplate().queryForList(sql, params);
        return DaoUtil.convertSQLResultForEntityList(tClass, maps);
    }

    /**
     * 查询实体
     * @param tClass
     * @param sql
     * @param params
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public <T> T execQuerySQLForEntity(Class<T> tClass,String sql,String ... params)throws InstantiationException, IllegalAccessException {
        Map <String, Object> maps = getJdbcTemplate().queryForMap(sql, params);
        return DaoUtil.convertSQLResultForEntity(tClass, maps);
    }

    /**
     * 保存方法
     * @param user
     * @throws IllegalAccessException
     */
    public void saveUser(User user) throws IllegalAccessException {
        String sql = DaoUtil.convertEntityForSQL(user);
        jdbcTemplate.execute(sql);
    }
    /**
     * 保存方法
     * @param user
     * @throws IllegalAccessException
     */
    public void save(User user) throws IllegalAccessException {
        String sql = DaoUtil.convertEntityForSQL(user);
        jdbcTemplate.execute(sql);
    }

}

DaoUtils:实体转化为SQL,查询结果转化为实体工具类

package com.mvc.utils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mvc.eitity.User;
import com.mvc.eitity.base.TableStructure;
import org.junit.Test;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.*;

public class DaoUtil {
    /**
     * 表结构Map
     */
    public static final Map<String,TableStructure> tableMap = new HashMap<>();
    /**
     * 封装spring template数据,返回对应实体
     *
     * @param <T>
     * @param tClass
     * @param result
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> List<T> convertSQLResultForEntityList(Class<T> tClass, List<Map<String, Object>> result) throws IllegalAccessException, InstantiationException {
        if(tClass == null || result == null){
            throw new NullPointerException("Class or resultData is null");
        }
        //获取实体
        final Map<String, String> columnFiledMap = columnFiledMap(tClass);
        List<T> resultList = new ArrayList<>();
        Gson gson = JsonUtil.getGson();
        for(Map<String,Object> data : result){
            resultList.add(convertSQLResultForEntity(tClass, data, columnFiledMap));
        }
        return resultList;
    }

    /**
     * 读取实体中注解内容,封装为字段名称和值
     * @param tClass
     * @return
     */
    public static Map<String,String> columnFiledMap(Class tClass){
        Map<String,String> columnFiledMap = new LinkedHashMap<>(16);
        Field[] fields = tClass.getDeclaredFields();
        for(Field field : fields){
            field.setAccessible(true);
            Column annotation = field.getAnnotation(Column.class);
            if(annotation != null){
                columnFiledMap.put(annotation.name(),field.getName());
            }
        }
        return columnFiledMap;
    }

    /**
     * 拼接字段和值转化实体
     * 实体的转换没有用到SET方法去注入
     * 而是选择了使用MAP通过JSON直接转化为实体
     * @param tClass
     * @param data
     * @param columnFiledMap
     * @param <T>
     * @return
     */
    public static <T> T convertSQLResultForEntity(Class<T> tClass,Map<String,Object> data,Map<String,String> columnFiledMap){
        Map<Object,Object> newObjectValue = new HashMap<>();
        for(Map.Entry<String,Object> entry : data.entrySet()){
            String newFiled = columnFiledMap.get(entry.getKey());
            newObjectValue.put(newFiled,entry.getValue());
        }
        return JsonUtil.formJson(JsonUtil.formatJson(newObjectValue), tClass);

    }

    /**
     * 转化实体为SQL,保存方法
     * @param ob
     * @return
     * @throws IllegalAccessException
     * 这个方法有缺陷,生成的SQL字段顺序不是和数据库中对应的,后续准备优化
     */
    public static synchronized String convertEntityForSQL(Object ob) throws IllegalAccessException {
        StringBuffer sql = new StringBuffer("insert into ");
        Class<?> aClass = ob.getClass();//获取传入对象的Class
        Field[] fields = aClass.getDeclaredFields();//反射获取对象的私有化字段
        Table entity = aClass.getAnnotation(Table.class);//获取实体中表名
        sql.append(entity.name());
        TreeSet<String> rowSet = new TreeSet<>();
        LinkedList<Object> valSet = new LinkedList<>();
        for(Field field : fields){//这里不想写两次循环所以没有调用上面的方法
            field.setAccessible(true);
            Column annotation = field.getAnnotation(Column.class);//获取Column注解的字段名称
            Id id = field.getAnnotation(Id.class);
            if(annotation != null){
                if(id!= null){
                    continue;//判断是否有ID注解,因为数据库里面id设置为自增所以拼接SQL的时候不用拼接ID
                }
                rowSet.add(annotation.name());
                valSet.add(String.valueOf(field.get(ob)));
            }
        }
        sql.append(disposeRowSQL(rowSet.toString()));
        sql.append(" VALUES (");
        for(Object val :valSet){
            sql.append("'" + val + "',");
        }
        if(sql.toString().endsWith(",")){
            sql.replace(sql.length() -1,sql.length(),"");
        }
        sql.append(")");
        return sql.toString();
    }
    public static <T> T convertSQLResultForEntity(Class<T> tClass,Map<String,Object> data){
        Map<String, String> stringStringMap = columnFiledMap(tClass);
        return convertSQLResultForEntity(tClass,data,stringStringMap);
    }

    private static String disposeRowSQL(String arg){
        return arg.replaceAll("\\[","(").replaceAll("\\]",")");
    }
    @Test
    public void junitOne() throws IllegalAccessException {
        convertEntityForSQL(new User(2,"2","3","4"));
    }
    @Test
    public void daoTest() throws IllegalAccessException {
        String s = convertEntityForSQL(new User(0, "a", "a", "b"));
        System.out.println(s);
    }
}

第一次写反射方法不对请留言,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值