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

记得第一次写项目的时候,傻傻的数据库一张表,代码里就写一个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操作。

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

测试代码:

打印结果:

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

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

时间: 2024-08-09 00:00:03

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

【WindowsPhone】利用反射初始化和添加 SQLite数据库

首先引用命名空间 using System.Reflection 了解一下 Assembly 类 // // 摘要: // 表示一个程序集,它是一个可重用.无版本冲突并且可自我描述的公共语言运行时应用程序构造块. public abstract class Assembly 我们把Model类都约定好放在同一个命名空间下,下面以User类为例: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 u

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

java关于反射机制的包主要在java.lang.reflect中,structs,hibernate,spring等框架都是基于java的反射机制. 下面是一个关于利用java的反射机制,实现了对私有属性和私有方法的访问的简单例子,希望能对你有所帮助. import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; public class Person { private

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

通过学习其它大神的经验,从而自己研究这套代码,感谢那些分享知识的大神,因此我也将自己整理的内容贡献出来,以供大家共同进步.谢谢. 这两个类,可以做好后直接生成一个jar文件,从而下次项目直接导入jar文件就可以调用了. MyJDBC.properties 这个文件放在项目文件的src文件下,里面的配置内容如下: conURL=jdbc:sqlserver://192.168.1.1:1433;databaseName=数据库名称 cname=com.microsoft.sqlserver.jdb

反射(三)——反射技术的应用

反射技术的应用 前面我们学习了反射机制,接下来我们就进一步来谈谈它的应用.比如我们已经定义了一个集合类,其中的 泛型为String,那我们能向该集合添加其他类型的元素吗?从java的语法上是无法做到的. ArrayList<String> array = new ArrayList<String>(); array.add("String"); //向集合添加String类型 array.add(123); //无法添加Integer等其他数据类型 如上代码,我

NPOI操作excel——利用反射机制,NPOI读取excel数据准确映射到数据库字段

> 其实需求很明确,就是一大堆不一样的excel,每张excel对应数据库的一张表,我们需要提供用户上传excel,我们解析数据入库的功能实现. 那么,这就涉及到一个问题:我们可以读出excel的表头,但是怎么知道每个表头具体对应数据库里面的字段呢? 博主经过一段时间的思考与构思,想到一法:现在的情况是我们有excel表A,对应数据库表B,但是A与B具体属性字段的映射关系我们不知.那我们是不是可以有一个A到B的映射文件C呢? 我想,说到这,大家就很明了了... 第一步:为每张excel创建一个与

IT观察】网络通信、图片显示、数据库操作……Android程序员如何利用开源框架

每个Android 程序员都不是Android应用开发之路上孤军奋战的一个人,GitHub上浩如烟海的开源框架或类库就是前人为我们发明的轮子,有的轮子能提高软件性能,而有的轮子似乎是以牺牲性能为代价换取编程速度.擅长利用轮子的程序员已经遥遥领先,不擅长利用轮子的程序员总是嫌前人发明的轮子不够圆,自己造个方轮子上路后才发现落后了. 作者:玖哥来源:51CTO|2017-10-19 16:06 移动端 收藏 分享 [51CTO.com原创稿件]每个Android 程序员都不是Android应用开发之

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理 2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论:0 | 浏览:45 | 该类在MVC中可以方便管理配置信息,可以直接把Model储存进数据库或者从数据库去除数据转为Model. 1 何为配置项目? 比如网站的名称,页脚信息,meta中的KeyWord信息等,如果不想硬编码到网页里,就需要使用配置文件进行储存,通常都是储存到数据库中.使用的时候读取出来

利用SQL Profiler 追踪数据库操作

原文:利用SQL Profiler 追踪数据库操作 SQL Server 事件探查器 是一个界面,用于创建和管理跟踪并分析和重播跟踪结果. 这些事件保存在一个跟踪文件中,稍后试图诊断问题时,可以对该文件进行分析或用它来重播一系列特定的步骤. SQL Server 事件探查器# Microsoft SQL Server 事件探查器 是 SQL 跟踪的图形用户界面,用于监视 数据库引擎 或 Analysis Services 的实例. 您可以捕获有关每个事件的数据并将其保存到文件或表中供以后分析. 

利用反射动态操作数组

java语言中,数组对象并不是从某个类实例化出来的,而是JVM动态创建的.对数组对象使用如下操作,可看到数组对应的Class对象.通过RTTI(Run-Time Type Information)可直接检查数组的运行时类型,以及它的签名.下方的 "[L"就是int[]/Integer[] 的运行类型. 1 Integer[] integers = (Integer[]) Array.newInstance(Integer.class,4); 2 System.out.println(i