记得第一次写项目的时候,傻傻的数据库一张表,代码里就写一个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")){
                );
                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();
                }
            }
        }
        ;i<fieldNames.size();++i){
            ){
                sql.append(fieldNames.get(i));
            }
            else{
                sql.append(","+fieldNames.get(i));
            }
        }
        sql.append(") values (");
        ;i<fieldValues.size();++i){
            ){
                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语句,运行。这个应该简单了吧

        运行结果如图:

                

/1a0aa07e-0fe3-40f1-acb3-3bf8b91c0fe1/wH7XOU2B7hk6mDG.NJ6K11Is1C7GqJqJztQNMuBBeD0!/o/dFKSfW96JAAA&bo=zQAsAM0ALAADACU!" style="vertical-align:top; width:205px; height:44px"> 

 

        

/1a0aa07e-0fe3-40f1-acb3-3bf8b91c0fe1/.4qfDNoRX4A*p9pkcCxjZaLoQ953i6T*KsUuxpP*160!/o/dAe37G44IwAA&bo=DwIwAA8CMAADACU!" style="vertical-align:top; width:527px; height:48px">

代码大致是这样子的,可是从健壮性上去考虑的话。还有非常多地方须要改动,这里仅仅是用来简单说明怎样利用反射来实现这样的统一的DAO操作。

 
关于查询,能够自己练习一下,也是相同利用反射拼凑出来,可是查询的关键在于怎样利用反射把查到数据包装成你须要的一个实体类。

測试代码:

/1a0aa07e-0fe3-40f1-acb3-3bf8b91c0fe1/HeQy6owjUTVdq0z9LqiGGaskocmRWOu6utHKj.4YkgA!/o/dNiZem99JAAA&bo=AwJvAAMCbwADACU!" style="vertical-align:top; width:515px; height:111px">

打印结果: 

/1a0aa07e-0fe3-40f1-acb3-3bf8b91c0fe1/KLFBBe*EZD1yobXGz2iS3IVb0EuJ4xRibwrrAJzqC00!/o/dGvRg29xJAAA&bo=wgBxAMIAcQADACU!" style="vertical-align:top; width:0px">

/1a0aa07e-0fe3-40f1-acb3-3bf8b91c0fe1/oUM8BuiICbnS2C4u7BO4APESgCj9yKG9WlVFFNPzveY!/o/dKmO6W4.IwAA&bo=wgNYAMIDWAADACU!" style="vertical-align:top; width:870px; height:79px">

这里没用泛型的一个不好的地方在于,操作时常常须要进行强制类型转换。后面能够考虑利用泛型。

利用反射技术实现POJO的数据库操作的更多相关文章

  1. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  2. Java JDBC利用反射技术将查询结果封装为对象

    1.JDBC将返回结果集封装成对象demo class JdbcDemo { /** * 获取数据库列名 * @param rs * @return */ private static String[ ...

  3. 【转】【Java】利用反射技术,实现对类的私有方法、变量访问

    java关于反射机制的包主要在java.lang.reflect中,structs,hibernate,spring等框架都是基于java的反射机制. 下面是一个关于利用java的反射机制,实现了对私 ...

  4. 万能的JDBC工具类。通过反射机制直接简单处理数据库操作

    package com.YY.util; import java.io.IOException; import java.io.InputStream; import java.sql.Connect ...

  5. JDBC 利用反射技术将查询结果封装为对象(简单ORM实现)

    ORM(Object Relational Mapping)对象关系映射 public class ORMTest { public static void main(String[] args) t ...

  6. 结合java的反射和泛型性质简化JDBC和相应的同步等服务器数据库操作代码

    github地址:https://github.com/hzphzp/HeartTrace_Server 我们的服务器端数据库并没有用sqllite, 而是直接用mysql,并且用JDBC直接进行操作 ...

  7. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  8. Java开发笔记(七十九)利用反射技术操作私有属性

    早在介绍多态的时候,曾经提到公鸡实例的性别属性可能被篡改为雌性,不过面向对象的三大特性包含了封装.继承和多态,只要把性别属性设置为private私有级别,也不提供setSex这样的性别修改方法,那么性 ...

  9. Java开发笔记(八十)利用反射技术操作私有方法

    前面介绍了如何利用反射技术读写私有属性,不单是私有属性,就连私有方法也能通过反射技术来调用.为了演示反射的逆天功能,首先给Chicken鸡类增加下列几个私有方法,简单起见弄来了set***/get** ...

随机推荐

  1. linux终端颜色控制

    引言: 由于在c代码中看到过打印彩色字, 又对PS1 想进一步了解,才有了这篇博文.----------------------------------------Linux 终端控制台字体颜色  - ...

  2. 【php】 给数组重建索引

    array_values $a = [1,2]; unset($a[1]); $a[] = 3; print_r($a); // 输出 [0=>1,2=>3]

  3. PAT Basic 1027

    1027 打印沙漏 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个“*”,要求按下列格式打印 ***** *** * *** ***** 所谓“沙漏形状”,是指每行输出奇数个符号:各行 ...

  4. node.js中的http.request方法使用说明

    http.get(options, callback) 由于该方法属于http模块,使用前需要引入http模块(var http= require(“http”) ) 接收参数: option   数 ...

  5. iOS WKWebView

    Webkit 是 iOS 8.0 后提供的新的框架,组件WKWebView比较UIWebView 速度更快.占用内存更少了,可支持性更多 WKWebView可通过KVO监听属性 title.estim ...

  6. 【编程工具】如何用Sublime Text3建立本地服务器和站点

    不久前,我学习了使用DW(DreamWare CS6)这款软件来学习HTML和制作静态网页,但是总觉得这款图形化软件不太适合我这种喜欢写代码的码农,所以最终我使用的是Sublime Text3这款软件 ...

  7. LINUX远程强制重启/proc/sys/kernel/sysrq /proc/sysrq-trigger

    1.     # echo 1 > /proc/sys/kernel/sysrq 2.     # echo b > /proc/sysrq-trigger 1. /proc/sys/ke ...

  8. 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分

    题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...

  9. HDU 5833 Zhu and 772002 ——线性基

    [题目分析] 这题貌似在UVA上做过,高精度高斯消元. 练习赛T2,然后突然脑洞出来一个用Bitset的方法. 发现代码只需要30多行就A掉了 Bitset大法好 [代码] #include < ...

  10. USACO Runaround Numbers

    题目大意:问最近的比n大的循环数是多少 思路:第n遍暴力大法好 /*{ ID:a4298442 PROB:runround LANG:C++ } */ #include<iostream> ...