你的位置:首页 > Java教程

[Java教程]自己写ORM框架 DBUtils_DG Java(C#的写在链接里)


ORM框架想必大家都比较熟知了,即对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。 当你开发一个应用程序的时候(不使用O/R MAPPING),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。

现在流行的ORM框架有:
JAVA系列:APACHE OJB,CAYENNE,JAXOR,JPA,HIBERNATE,IBATIS/MYBATIS,JRELATIONALFRAMEWORK,SMYLE,TOPLINK等
其中 TOPLINK 是 ORACLE 的商业产品,其他均为开源项目。其中 HIBERNATE的轻量级 ORM 模型逐步确立了在 JAVA ORM 架构中领导地位,甚至取代复杂而又繁琐的 EJB 模型而成为事实上的 JAVA ORM 工业标准。
.NET系列:EF(ENTITY FRAMWORK),NHIBERNATE,Ibits,ENTITYSCODEGENERATE,LINQ TOSQL,GROVE,RUNGOO.ENTERPRISEORM,FIRECODE CREATOR,MYGENERATION,CODESMITH PRO,CODEAUTO等
微软VS中自带的有EF(ENTITY FRAMWORK)框架。


你在DAO中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。我们可不可以写一个类来封装这些重复的劳动呢?

想必大家都有曾经想过写DBUtils_DG吧,实际上,从DBUtils_DG一步步写下来,封装到足够好之后,就会成为一个自己专属的ORM框架了。

在这里,小编写了一个很基础的类ORM的DBUtils_DG里面仅仅对Select查询语句进行了封装,由于考虑到了反射机制的诟病(这里不再讨论,关于反射效率问题有大多数的讨论,利与弊总是同时存在的,我们不纠结于这点)。对于常见的CRUD来说,CUD通常一个方法可以实现,并且Sql语句可以得到更大的封装结合配置文件和反射机制进行操作。小编这里采用的模式是MySql+DBUtils_DG+代码生成器(需要代码生成器的可以联系本人,不定期更新)来完成的代码编写工作,因此没有对CUD进行大量的封装,同时也提高了执行效率(你懂的)。

接下来我贴上我的代码(里面注释采用中文注释,比较完善有不懂的可以咨询本人):

 1 package liuyanban.Utils; 2  3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.lang.reflect.Field; 6 import java.sql.CallableStatement; 7 import java.sql.Connection; 8 import java.sql.DriverManager; 9 import java.sql.PreparedStatement; 10 import java.sql.ResultSet; 11 import java.sql.ResultSetMetaData; 12 import java.sql.SQLException; 13 import java.util.ArrayList; 14 import java.util.List; 15 import java.util.Properties; 16  17 import org.json.JSONArray; 18 import org.json.JSONObject; 19  20 public abstract class DBUtils_DG { 21   // 数据库驱动类名称 22   private static String driver_class = null;       //"com.mysql.jdbc.Driver"; 23   // 连接字符串 24   private static String driver_url = null;        //"jdbc:mysql://localhost:3306/db_liuyanban"; 25   // 用户名 26   private static String database_user = null;        //"root"; 27   // 密码 28   private static String database_password =null;      // "root"; 29   // 创建数据库连接对象 30   private static Connection connnection = null; 31   // 创建结果集对象 32   private static ResultSet resultSet = null; 33   // 创建PreparedStatement对象 34   private static PreparedStatement preparedStatement = null; 35   // 创建CallableStatement对象 36   private static CallableStatement callableStatement = null; 37  38   static { 39     try { 40       Properties properties = new Properties(); 41       InputStream fis = DBUtils_DG.class.getClassLoader().getResourceAsStream("db.properties");// 加载数据库配置文件到内存中放在同src下 42       try { 43         properties.load(fis);// 获取数据库配置文件 44         driver_class = properties.getProperty("driver_class").toString(); 45         driver_url =properties.getProperty("driver_url").toString(); 46         database_user =properties.getProperty("database_user").toString(); 47         database_password =properties.getProperty("database_password").toString(); 48       } catch (IOException e) { 49         e.printStackTrace(); 50       } 51       Class.forName(driver_class); // 加载数据库驱动程序 52     } catch (ClassNotFoundException e) { 53       System.out.println("加载驱动错误"); 54       System.out.println(e.getMessage()); 55     } 56   } 57   /** 58    * 所有执行方法的辅助器(共同参与的部分) 59    * @param sql SQL语句 60    * @param params 参数数组,若没有参数则为null 61   */ 62   private static void SqlPrepareCommand(String sql, Object... params) 63   { 64     try { 65       // 获得连接 66       connnection = DriverManager.getConnection(driver_url, database_user, database_password); 67       // 调用SQL 68       preparedStatement = connnection.prepareStatement(sql); 69       // 参数赋值 70       if (params != null) { 71         for (int i = 0; i < params.length; i++) { 72           preparedStatement.setObject(i + 1, params[i]); 73         } 74       } 75     } catch (Exception e) { 76       System.out.println(e.getMessage()); 77     } 78   } 79  80   /** 81    * insert update delete SQL语句的执行的统一方法 82    * @param sql SQL语句 83    * @param params 参数数组,若没有参数则为null 84    * @return 受影响的行数 85   */ 86   public static boolean executeUpdate(String sql, Object...params) { 87     try { 88       SqlPrepareCommand(sql, params);//调用通用的初始化方法来设置参数 89       return preparedStatement.executeUpdate()>0?true:false;// 执行 90     } catch (SQLException e) { 91       System.out.println(e.getMessage()); 92       return false; 93     } finally { 94       // 释放资源 95       closeAll(); 96     } 97   } 98  99   /**100    * SQL 查询将查询结果直接放入ResultSet中101    * @param sql SQL语句102    * @param params 参数数组,若没有参数则为null103    * @return 结果集104   */105   public static ResultSet executeQueryResultSet(String sql, Object... params) {106     try {107       SqlPrepareCommand(sql, params);        //调用通用的初始化方法来设置参数108       return preparedStatement.executeQuery();   // 执行109     } catch (SQLException e) {110       System.out.println(e.getMessage());111       return null;112     }113   }114 115   /**116    * SQL 查询将查询结果:一行一列 (左上角的结果)117    * @param sql SQL语句118    * @param params 参数数组,若没有参数则为null119    * @return 结果集120   */121   public static Object executeQuerySingleData(String sql, Object... params) {122     try {123       resultSet=executeQueryResultSet(sql, params);124       return resultSet.next()?resultSet.getObject(1):null;125     } catch (SQLException e) {126       System.out.println(e.getMessage());127       return null;128     } finally {129       closeAll();130     }131   }132   /**133    * SQL 查询将查询结果:一行 返回class类型的对象(第一行结果)134    * @param sql SQL语句135    * @param params 参数数组,若没有参数则为null136    * @return 结果集137   */138   public static <T> T executeQuerySingleLine(Class<T> clazz,String sql, Object... params) {139     try {140       resultSet=executeQueryResultSet(sql, params);                //从数据库获得结果集141       if(resultSet != null) {142         ResultSetMetaData rsmd = resultSet.getMetaData();             // 获得结果集的MetaData143         T t = clazz.newInstance();                         // 通过反射创建 T 实例144         while(resultSet.next()){145           for(int i=1;i<=rsmd.getColumnCount();i++){146             Field tField =clazz.getDeclaredField(rsmd.getColumnLabel(i));  //获取到单行记录对应的字段147             tField.setAccessible(true);                    //设置通过反射访问该Field时取消访问权限检查148             tField.set(t, resultSet.getObject(rsmd.getColumnLabel(i)));    //获取到每一行结果对应字段的值并赋值给类属性149           }150         }151         return t;                                 //返回赋值后的T对象152       } else return null;153     } catch (Exception e) {154       return null;155     }156   }157 158   /**159    * 获取结果集,并将结果放在List中生成List<T> (多行数据)160    * @param clazz 类161    * @param sql SQL语句162    * @params List结果集163   */164   public static <T> List<T> executeQueryList(Class<T> clazz,String sql, Object... params) {165     try {166       resultSet=executeQueryResultSet(sql, params);                //从数据库获得结果集167       List<T> list = new ArrayList<T>();                     //实例化一个泛型List<T>保存结果的List168       try {169         ResultSetMetaData rsmd = resultSet.getMetaData();             // 获得结果集的MetaData170         while (resultSet.next()){171           T t = clazz.newInstance();                       // 通过反射创建 clazz 实例172           for(int i=1;i<=rsmd.getColumnCount();i++){173             try {174               Field tField =clazz.getDeclaredField(rsmd.getColumnLabel(i));  //获取到单行记录对应的字段175               tField.setAccessible(true);                    //设置通过反射访问该Field时取消访问权限检查176               tField.set(t, resultSet.getObject(rsmd.getColumnLabel(i)));    //获取到每一行结果对应字段的值并赋值给类属性177             } catch (Exception e) {178               continue;179             }180           }181           list.add(t);                            //将实例化赋值的对象存到List<T>中182         }183       } catch (Exception e) {184         System.out.println(e.getMessage());185         return null;186       }187       return list;//返回填充对象的list188     } finally {189       closeAll();//调用自定义的关闭所有资源方法关闭所有资源190     }191   }192 193   /**194    * 存储过程带有一个输出参数的方法195    * @param sql 存储过程语句196    * @param params 参数数组197    * @param outParamPos 输出参数位置198    * @param SqlType 输出参数类型199   */200   public static Object executeQueryProcedure(String sql, Object[] params,int outParamPos, int SqlType) {201     Object object = null;202     try {203       connnection = DriverManager.getConnection(driver_url, database_user, database_password);204       // 调用存储过程205       callableStatement = connnection.prepareCall(sql);206       // 给参数赋值207       if(params != null) {208         for(int i = 0; i < params.length; i++) {209           callableStatement.setObject(i + 1, params[i]);210         }211       }212       // 注册输出参数213       callableStatement.registerOutParameter(outParamPos, SqlType);214       // 执行215       callableStatement.execute();216       // 得到输出参数217       object = callableStatement.getObject(outParamPos);218 219     } catch (SQLException e) {220       System.out.println(e.getMessage());221     } finally {222       // 释放资源223       closeAll();224     }225     return object;226   }227   /**228    * 将查询到的单行数据转换成JsonObject229    * @param sql SQL语句230    * @param params 参数数组,若没有参数则为null231    * @return JSONObject结果232   */233   public static JSONObject executeQuerySingleLineToJsonObject(String sql, Object... params)234   {235     try {236       resultSet=executeQueryResultSet(sql, params);                //从数据库获得结果集237       JSONObject jsonObject=new JSONObject();238       if(resultSet != null) {239         ResultSetMetaData rsmd = resultSet.getMetaData();             // 获得结果集的MetaData240         while(resultSet.next()){241           for(int i=1;i<=rsmd.getColumnCount();i++){242             jsonObject.put(rsmd.getColumnLabel(i), resultSet.getObject(rsmd.getColumnLabel(i)));243           }244         }245         return jsonObject;                                 //返回赋值后的T对象246       } else return null;247     } catch (Exception e) {248       return null;249     }250   }251   /**252    * 将ResultSet数据转换成JsonArray253    * @param sql SQL语句254    * @param params 参数数组,若没有参数则为null255    * @return JSONArray结果集256   */257   public static JSONArray executeQueryResultSetToJsonArray(String sql, Object... params)258   {259     try {260       resultSet= executeQueryResultSet(sql, params);261       JSONArray jsonArray=new JSONArray();262       if(resultSet != null) {263         ResultSetMetaData rsmd = resultSet.getMetaData();// 获得结果集的MetaData264         while(resultSet.next()){265           JSONObject jsonMember =new JSONObject();266           for(int i=1;i<=rsmd.getColumnCount();i++){267             jsonMember.put(rsmd.getColumnLabel(i), resultSet.getObject(rsmd.getColumnLabel(i)));268           }269           jsonArray.put(jsonMember);270         }271         return  jsonArray;//返回赋值后的T对象272       } else return null;273     } catch (Exception e) {274       System.err.println(e.getMessage());275       return null;276     }277   }278   /**279    * 关闭所有资源280   */281   private static void closeAll() {282     // 关闭结果集对象283     if (resultSet != null) {284       try {285         resultSet.close();286       } catch (SQLException e) {287         System.out.println(e.getMessage());288       }289     }290     // 关闭PreparedStatement对象291     if (preparedStatement != null) {292       try {293         preparedStatement.close();294       } catch (SQLException e) {295         System.out.println(e.getMessage());296       }297     }298     // 关闭CallableStatement 对象299     if (callableStatement != null) {300       try {301         callableStatement.close();302       } catch (SQLException e) {303         System.out.println(e.getMessage());304       }305     }306     // 关闭Connection 对象307     if (connnection != null) {308       try {309         connnection.close();310       } catch (SQLException e) {311         System.out.println(e.getMessage());312       }313     }314   }315 }

DBUtils_DG

db.properties是外部的一个配置文件,里面对数据库的一些信息进行配置,具体配置信息如下:

1 driver_class=com.mysql.jdbc.Driver2 driver_url=jdbc\:mysql\://localhost\:3306/db_liuyanban3 database_user=root4 database_password=root

内部的一些主要方法介绍:

executeUpdate 执行sql命令,返回受影响的行数,通过受影响的行数进而判断是否执行成功! 一般用作CUD操作

executeQuerySingleData 执行sql语句或存储过程 返回单个数据 (如返回自增的ID)

public static ResultSet executeQueryResultSet(String sql, Object... params)执行sql语句或存储过程 返回ResultSet

public static JSONObject executeQuerySingleLineToJsonObject(String sql, Object... params) 执行sql语句,查询单行数据返回一个JSONObject(Object对象转成的JSONObject)

public static JSONArray executeQueryResultSetToJsonArray(String sql, Object... params) 执行sql语句,查询单行数据返回一个JSONArray(list对象转成的JSONArray)

executeQueryProcedure 执行存储过程

public static <T> List<T> executeQueryList(Class<T> clazz,String sql, Object... params)反射返回一个List T 类型的结果集 如List<User> 用于Reader操作

public static <T> T executeQuerySingleLine(Class<T> clazz,String sql, Object... params) 反射返回一个T类型的结果 如User 用于Reader操作


接下来我们介绍一下使用方法 :

这里采用的使用地方是我自己以前写过的一个留言板的Dao层,这里面有对我的DBUtils_DG的使用,具体见代码:

 1 package liuyanban.dao; 2  3 import liuyanban.Utils.DBUtils_DG; 4 import liuyanban.entity.User; 5 import sun.org.mozilla.javascript.internal.EcmaError; 6  7 import java.util.List; 8  9 /**10  * Created by Administrator on 2016/8/22.11 */12 public class UserDaoImpl implements IUserDao {13   //增删改14   public boolean addUser(User user) {15     if (this.isExistUesr(user.getLoginId())) return false;//当登录名已存在时不能进行注册16     String sql="insert into tb_user (loginId,Pwd,Name,jurisdiction,Image) values (?,?,?,?,?)";17     Object[]objects={user.getLoginId(),user.getPwd(),user.getName(),user.getJurisdiction(),user.getImage()};18     return DBUtils_DG.executeUpdate(sql,objects);19   }20 21   public boolean updataUser(User user) {22     String sql="update tb_user set loginId=?,Pwd=?,Name=?,jurisdiction=?,Image=? where userId=?";23     Object[]objects={user.getLoginId(),user.getPwd(),user.getName(),user.getJurisdiction(),user.getImage(),user.getUserId()};24     return DBUtils_DG.executeUpdate(sql,objects);25   }26   public boolean deleteUser(User user) {27     String sql="delete from tb_user where userId=?";28     return DBUtils_DG.executeUpdate(sql,user.getUserId());29   }30   //查询31   //获得所有User32   public List<User> getUserAll() {33     String sql="select userId,loginId,`Name`,Jurisdiction,Image from tb_user";34     return DBUtils_DG.executeQueryList(User.class,sql);35   }36   //通过Id 获得User对象37   public User getUserByUserId(int userId) {38     String sql="select userId,loginId,`Name`,Jurisdiction,Image from tb_user where userId=? limit 1";39     return DBUtils_DG.executeQuerySingleLine(User.class,sql,userId);40   }41 42   public boolean isExistUesr(String loginId) {43     String sql="select loginId from tb_user where loginId=? limit 1";44     try{45       return DBUtils_DG.executeQuerySingleData(sql,loginId).toString().length()>0?true:false;46     }47     catch (Exception ee)48     {49       return false;50     }51   }52 53   //通过loginId 获得User对象54   public User getUserByloginId(String loginId)55   {56     String sql="select * from tb_user where loginId=? limit 1";57     return DBUtils_DG.executeQuerySingleLine(User.class,sql,loginId);58   }59 }

UesrDaoImpl

写到这里,相信大家都已经对ORM框架的实现机制有一定的了解,并且能完美的实现一个DBUtils来进行对自己数据访问代码的封装!如果喜欢,大家可以进一步对DAO层的代码进行封装放到一个类里面,更加方便自己对数据库的访问,可以更加简便地访问数据库,有朝一日写出一个属于自己的ORM框架!


 

有关于C#的SqlHelper介绍详情请参考:http://www.cnblogs.com/qixiaoyizhan/p/5818298.html

2016-08-29 16:44:12

本文为七小站主原创作品,转载请注明出处:http://www.cnblogs.com/qixiaoyizhan/