JDBC之运用反射模拟ORM


上一篇我们使用了结果集元数据实现了将结果集封装到List<Map<K,V>>中返回.

ORM:对象-关系数据库映射(Object/Relation Mapping).以简单的方式提供了领域对象模型与数据库间的映射.典型的Hibernate,iBatis

这里仅是练习.功能还很弱.

程序目的:传入sql语句返回字段如果和传入对象模型的setXX方法对应则自动赋值.并返回该对象.

首先构建User模型.应该和数据库字段相对应.数据库结构如下:

User模型:

packagecom.test.reflection;

publicclassUser{
privateIntegerid;
privateStringfirstname;
privateStringlastname;
privateIntegerage;

//约定的默认构造器(必须)
publicUser(){

}

@Override
publicStringtoString(){
return"id:"+this.id+"firstname:"+this.firstname
+"lastname:"+this.lastname+"age:"+this.age;
}

publicIntegergetId(){
returnid;
}

publicvoidsetId(Integerid){
this.id=id;
}

publicStringgetFirstname(){
returnfirstname;
}

publicvoidsetFirstname(Stringfirstname){
this.firstname=firstname;
}

publicStringgetLastname(){
returnlastname;
}

publicvoidsetLastname(Stringlastname){
this.lastname=lastname;
}

publicIntegergetAge(){
returnage;
}

publicvoidsetAge(Integerage){
this.age=age;
}

}

然后是上次提供的DBUtils:

packagecom.test.jdbc;

importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.SQLException;

publicfinalclassDBUtils{
privatestaticStringurl="jdbc:mysql://localhost:3306/mytest";
privatestaticStringuser="root";
privatestaticStringpassword="root";

//获得连接
publicstaticConnectiongetConn()throwsSQLException{
returnDriverManager.getConnection(url,user,password);
}

//释放连接
publicstaticvoidfree(ResultSetrs,PreparedStatementps,Connectionconn){
try{
if(rs!=null){
rs.close();
}
}
catch(SQLExceptione){
e.printStackTrace();
}
finally{
try{
if(ps!=null){
ps.close();
}
}
catch(SQLExceptione){
e.printStackTrace();
}
finally{

try{
if(conn!=null){
conn.close();
}
}
catch(SQLExceptione){
e.printStackTrace();
}

}

}

}

//加载驱动
static{
try{
Class.forName(
"com.mysql.jdbc.Driver");
}
catch(ClassNotFoundExceptione){
System.out.println(
"驱动加载出错");
}
}

}

最后最主要的ORMExample:

packagecom.test.reflection;

importjava.lang.reflect.Method;
importjava.sql.Connection;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.ResultSetMetaData;

importcom.test.jdbc.DBUtils;

publicclassORMExample{

publicstaticvoidmain(String[]args){
Useruser
=(User)getObject(
"selectid,firstname,lastname,agefromuserswhereid=1",
User.
class);
System.out.println(user);

}

publicstatic<T>TgetObject(Stringsql,Class<T>clazz){
Connectionconn
=null;
PreparedStatementps
=null;
ResultSetrs
=null;

try{
conn
=DBUtils.getConn();
ps
=conn.prepareStatement(sql);
rs
=ps.executeQuery();
//必须有无参的构造函数
Tobj=null;
//获得共有方法
Method[]ms=clazz.getMethods();
//通过结果集元数据获得列数
ResultSetMetaDatarsmd=rs.getMetaData();
intcolumnCount=rsmd.getColumnCount();

if(rs.next()){
obj
=clazz.newInstance();
for(inti=1;i<=columnCount;i++){
StringcolName
=rsmd.getColumnLabel(i);
StringmethodName
="set"
+colName.substring(0,1).toUpperCase()
+colName.substring(1);
//循环读取所有方法
for(Methodm:ms){
//列名和set方法名如果相同则调用该方法
if(methodName.equals(m.getName())){
m.invoke(obj,rs.getObject(colName));
}
}
}
}
returnobj;
}
catch(Exceptione){
thrownewRuntimeException();
}
finally{
DBUtils.free(rs,ps,conn);
}
}
}

数据库值如下:

代码运行结果为:

id:1firstname:lastname:age:23

具体的方法可见代码注释.通过反射获取方法和元数据的列比较相同的便动态执行.

下篇将要介绍自己写连接池.待续.

优质内容筛选与推荐>>
1、最短路总结
2、Kubernetes-1.4.x集群
3、移动端兼容性浅析
4、Spring Boot全日志设置
5、spring aop 获取拦截的方法(Method对象)


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn