码迷,mamicode.com
首页 > 数据库 > 详细

利用反射技术实现POJO的数据库操作

时间:2015-07-19 15:03:22      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:java   数据库   

记得第一次写项目的时候,傻傻的数据库一张表,代码里就写一个DAO类,几张表就写几个DAO类,大量的重复代码,自己粘着都嫌烦,后来接触了Hibernate,不得不说对我们这种小白用处还是很大的,那么多的实体类,一个DAO就可以实现基本的数据库操作了,于是我用的不亦乐乎,但到底是怎么做的,从来没有考虑过,现在用这些框架已经有一段时间了,原谅我脑洞大开,想自己实现一下这种类似的功能:

在准备写之前,我们需要一些规则:
    1、由实体类名,可以知道我这个类是存放在哪张表里---这里我采用的是和t_类名
    2、由实体类中的变量名可以知道对应表中的字段名的一一这里我采用f_变量名做为字段名
    3、实体类里,有着对变量的赋值与获取,且方法名有一定的规则----比如我们常用的get、set方法 ,这里我也是采用这种方法

一、利用如上规则设计相关的类与表:
我这里写了两个实体类customer和admin,并在类中多加了一个toString方法,便于后面打印信息查看:
 
package com.java.reflect.database;
public class Customer {
    private Long id;
    private String username;
    private String password;
    private String realname;
    private String address;
    private String email;
    private String mobile;
    
    @Override
    public String toString() {
        return "Customer [id=" + id + ", username=" + username + ", password="
                + password + ", realname=" + realname + ", address=" + address
                + ", email=" + email + ", mobile=" + mobile + "]";
    }
    
    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 String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getRealname() {
        return realname;
    }
    public void setRealname(String realname) {
        this.realname = realname;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getMobile() {
        return mobile;
    }
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
}
 
类似可以写admin,都贴出来的话会很长,就不贴了,对应的表结构设计如下:
 
技术分享                                   技术分享
 
二、利用反射拼出对应的数据库操作语句

保存语句拼凑:
 
public static String saveSql(Object o){
        StringBuilder sql = new StringBuilder();
        Class c = o.getClass();
        
        sql.append("INSERT INTO ");
        
        Method[] methods = c.getMethods();
        String cName = c.getName();
        ArrayList<String> fieldNames = new ArrayList<String>();
        ArrayList<Object> fieldValues = new ArrayList<Object>();
        
        String tableName = "t_"+cName.substring(cName.lastIndexOf(".")+1,cName.length());
        
        sql.append(tableName);
        sql.append(" (");
        
        for(Method method : methods){
            String mName = method.getName();
            if(mName.startsWith("get"&& !mName.startsWith("getClass")){
                String fName = "f_"+mName.substring(3);
                fieldNames.add(fName);
                try{
                    Object value = method.invoke(o, null);
                    if(value instanceof String){
                        fieldValues.add("\""+value+"\"");
                    }
                    else{
                        fieldValues.add(value);
                    }
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
        for(int i = 0;i<fieldNames.size();++i){
            if(i==0){
                sql.append(fieldNames.get(i));
            }
            else{
                sql.append(","+fieldNames.get(i));
            }
        }
        sql.append(") values (");
        for(int i = 0;i<fieldValues.size();++i){
            if(i==0){
                sql.append(fieldValues.get(i));
            }
            else{
                sql.append(","+fieldValues.get(i));
            }
        }
        sql.append(")");
        return sql.toString();
    }
 
这里的重点在于利用反射拼凑SQL语句的过程----
    1、这个函数的参数类型是什么?如何接收一个任意的实体类?
    这里我用的是object,因为无论你传什么样的一个参数过来,其都是Objcet类的一个子类,用Object没有问题,这里我在考虑后面利用泛型,不过这样的话在后面查询的话,实例化的时候要麻烦一点。暂时先不考虑。
    
    2、如何知道这个实体类的类名?并找到对应的表?
    利用函数getClass得到这个实体类对应的类,再利用getName得到类名,包括包名,再按照你制定的规则解析出对应的表名

    3、开始拼凑sql语句,因为要反复的改变sql字符串,这里我用的StringBuilder对象,在插入的时候,我们的语句是这样的
        INSERT INTO 表名(字段名) VALUES (对应的值)
        这里我们有三个需要知道的变量,表名已经在第二步中拿到
        现在我们考虑拿字段名,拿到后存放到一个list里,首先拿我们所有的方法,找到以get开头的方法,我们按照对变量赋值时命名函数规则,所有以get开头的(我们把getClass排除在外),解析得到对应的字段名,这里对应我的语句:
 String fName = "f_"+mName.substring(3);
        有了字段名,接下来,拿对应的值,也存到相应的list里,这里取值用的method.invoke方法。请参照上面代码,为了拼凑方便,对于字符串,我直接以“xxxx”的形式存储。
        有了相应的值,接下就是拼凑了,这个应该没什么难度,最后对于任意一个对象,拼凑的结果如下,customer有点长没能截全: 
技术分享

三、利用已经拼凑好的sql语句,执行,这个应该简单了吧
        执行结果如图:
                技术分享 
 
        技术分享 

代码大致是这样子的,但是从健壮性上去考虑的话,还有很多地方需要修改,这里只是用来简单说明如何利用反射来实现这种统一的DAO操作。
 
关于查询,可以自己练习一下,也是同样利用反射拼凑出来,但是查询的关键在于如何利用反射把查到数据包装成你需要的一个实体类。 
测试代码: 
技术分享 
打印结果: 
技术分享技术分享
 
 这里没用泛型的一个不好的地方在于,操作时经常需要进行强制类型转换,后面可以考虑利用泛型。


版权声明:本文为博主原创文章,未经博主允许不得转载。

利用反射技术实现POJO的数据库操作

标签:java   数据库   

原文地址:http://blog.csdn.net/leox0808/article/details/46954555

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!