java攻城狮我们就爱程序媛

利用反射实现数据库CRUD操作

2017-09-16  本文已影响14人  大炮对着虫子

如果不能简单的把事情说清楚,说明你还没有完全明白。

最近学习框架的时候,一去看源码就各种懵逼与难受,所以去补了一波反射和动态代理。反射其实就是一波API,平时自己很少用到,陌生产生恐惧。

正常情况下的CRUD操作,JDBC

Bean

public class User 
{
    private int user_id;
    private String user_name;
    private String user_password;
    private String user_role;
、、、各种get set
    
}

DAO

public class UserDAO {
    private Connection conn=(Connection) ConnectFactory.getConnection();
    
    
    public List<User> selectAllUser()
    {
        List<User> list=new ArrayList<>();
        try
        {
            PreparedStatement st=null;
            String sql="select * from user";
            st=(PreparedStatement) conn.prepareStatement(sql);
            ResultSet rs=st.executeQuery(sql);
            while(rs.next())
            {
                User user=new User();
                
                
                user.setUser_name(rs.getString("user_name"));
                user.setUser_id(rs.getInt("user_id"));
                user.setUser_password(rs.getString("user_password"));
                user.setUser_role(rs.getString("user_role"));
                list.add(user);
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            ConnectFactory.closeConnection();
        }
        return list;
        
    }
}

那么问题来了,如果有10个表需要进行同样的操作,比如:查询表的所有信息,查询总记录数,插入一条信息等 这种通用操作的sql语句。就会用传统的JDBC操作,程序猿小哥表示ctrl+c ctrl+v 不过来。

利用反射实现CRUD操作
public class ReflexDAO {
    private Connection conn=(Connection) ConnectFactory.getConnection();
    
    /**
     * 查询 所有
     * @param c1
     * @return
     */
    public ArrayList selectAll(Class c1)  //如果查询ID,加个ID参数。ID作为主键默认 在Bean属性的 第一个。
    {
        ArrayList list=new ArrayList();
        try
        {
            PreparedStatement st=null;
            //数据库表的名字 ==bean类的名字
            String sql="select * from "+c1.getSimpleName();
            
            st=(PreparedStatement) conn.prepareStatement(sql);
            ResultSet rs=st.executeQuery(sql);
            
            Field [] fi=c1.getDeclaredFields();  //获取到 类对象 的所有属性
            while(rs.next())
            {
                
                Object ob=c1.newInstance();
                for (Field field : fi) {
                    field.setAccessible(true);
                    field.set(ob, rs.getObject(field.getName()));
                }
                
                list.add(ob);
            
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            ConnectFactory.closeConnection();
        }
        return list;
    }
public void insert(Object oj)
    {
        try
        {
            Class cl=oj.getClass();
            PreparedStatement st=null;
            
            
            Field [] fields=cl.getDeclaredFields(); //获取所有的属性
            StringBuffer sf=new StringBuffer();
            sf.append("insert into ");
            
            sf.append(cl.getSimpleName());
            sf.append("(");
            for (int i=1;i<fields.length;i++) {
                fields[i].setAccessible(true);  //让私有的可以被访问
                if(i==fields.length-1)
                {
                    sf.append(fields[i].getName());
                }
                else
                {
                    sf.append(fields[i].getName()+",");
                }
            
                
            }
            sf.append(") value(");
            
            for (int i=1;i<fields.length;i++) {
                
                if(i==fields.length-1)
                {
                    sf.append("?)");
                }
                else
                {
                    sf.append("?,");
                }
                
            }
            System.out.println(sf);
            st=(PreparedStatement) conn.prepareStatement(sf.toString());
            for (int i=1;i<fields.length;i++)
            {
                st.setObject(i, fields[i].get(oj));
            }
            
        
            st.executeUpdate();
    
            
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            ConnectFactory.closeConnection();
        }
    }

这样子,就能够实现一个方法到处浪。

值得注意的是:

数据库的表名 要和类名保持一致,如果不一致的话,需要用配置文件进行映射,框架一般也是这么做的。

这种方法的反射我只 用了 属性去反射,存在一些局限性:如果属性的个数多余表列属性的个数,那么就会报错。

上一篇 下一篇

猜你喜欢

热点阅读