Jdbc的普通封装
来源:互联网 发布:app软件培训多少钱 编辑:程序博客网 时间:2024/06/11 13:21
嗯,大家肯定是经常使用jdbc完成一些基本的数据库操作,但是每次有没有发现都是差不多同样子的操作呢?为了解决这个问题,下面给出一个基本的jdbc封装。在这个列子中,
采用了单例设计模式,并且很好的控制了线程并发问题。因为数据的操作,每个Connection, Statement, PreparedStatement,ResultSet对象,都可能造成线程并发问题,所以在这个
类里面,全部的对象都是在方法里面定义,这样子,每个方法都拥有自己的运行堆栈,从而在使用单列模式的情况下,也不会有线程并发问题。有时候,在我们刚开始使用jdbc的
时候,会直接把Connetion, Statement, PreparedStatement, ResultSet的对象定义为一个类的属性...那样子很容易造成并发问题。
这个类同样把数据库的配置,放在一个xml文件中,这样子更具有灵活性。在修改xml的情况下,既可以完成数据库的更换。
下面是xml的内容:
url=jdbc:mysql://localhost:3306/username=itaempassword=imitaemdbName=gdou_gymdriver=org.gjt.mm.mysql.Driver
下面是封装的JdbcTool工具类:package net.itaem.tool;import java.io.InputStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Properties;import java.util.Set;import net.itaem.po.Field;/** * 操作数据库的工具类,这个类负责建立于数据库的连接,负责执行update, insert, delete等基本的数据库操作 * 这个类大家可以直接使用,不需要考虑过多的线程问题 * 这个类写了通用的update, insert, delete等数据库访问方法,具体到特殊的查询,以及含有事务的sql组合 * 大家可以直接写在自己的dao中 * 注意点:调用了getConnection()之后,记得在宿主程序中关闭你所获得的Connection变量 * @author luohong * @date 2014-03-09 * */public class JdbcTool {private static JdbcTool instance = new JdbcTool();//这些属性不可以修改,只允许直接从 jdbc.cfg.properties读取private static String dbName; //数据库名字private static String url; //数据库连接的urlprivate static String username; //数据库用户名private static String password; //密码/** * 解析数据库的配置文件 * 从配置文件中读取数据库连接的 url, username, password, driver, database name等各种信息 * 以后要修改数据库的链接地址,直接修改配置文件,不要修改该类 * */static{try {Properties properties = new Properties();InputStream inputStream = JdbcTool.class.getClassLoader().getResourceAsStream("jdbc.cfg.properties");properties.load(inputStream);//加载数据库驱动Class.forName((String)properties.get("driver"));dbName = (String)properties.getProperty("dbName");url = (String)properties.getProperty("url");password = (String)properties.getProperty("password");username = (String)properties.getProperty("username");} catch (Exception e) {throw new RuntimeException("加载mysql驱动失败");}}/** * 这个类的访问接口,返回这个类的实例,每次访问,返回的都是同一个实例 * */public static JdbcTool getJdbcToolInstance(){return instance;}/** * 采用单列设计模式 * */private JdbcTool(){}/** * 获取数据库连接 * 返回的每个Connection都是 new 出来的唯一Connection * @return Connection 返回数据库的链接 * @exception RuntimeException 如果获取数据库连接失败,直接抛出运行时异常,调用者不需要捕获该异常 * */public Connection getConnection(){try {Connection conn = DriverManager.getConnection(url + dbName, username, password);return conn;} catch (SQLException e) {e.printStackTrace();throw new RuntimeException("获取数据库连接失败" + ",url:" + url + dbName + ",username:" + username + ", password:" + password);}}/** * 执行insert, update, delete的sql语句,如果操作影响结果 * @param sql 要执行的sql语句,形式:insert into student(name, number) values (?,?) * @param args 要执行数据库的sql参数,如果为null,直接执行sql语句 * @return 返回记录修改的数目,如果出现异常,返回 -1 * */public int executeUpdate(String sql, Object[] args){Connection conn = getConnection();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql);if(args != null && args.length > 0)//注入sql ? 的实际内容for(int i=0; i<args.length; i++)ps.setObject(i + 1, args[i]);//如果没有参数,直接执行return ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();return -1;}finally{//关闭数据库连接try {ps.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}}/** * 批量执行sql语句,调用该方法之间,必须组装好sql语句 * sql语句只能是增加,删除,修改三种类型的语句 * @param sqlArray 要批量执行的sql语句 * @return 返回批量执行后的int数组 * @exception SQLException * */public int[] executeUpdateBatch(String[] sqlArray){Connection conn = getConnection();Statement statement = null;try {statement = conn.createStatement();for(String sql : sqlArray)statement.addBatch(sql);return statement.executeBatch();} catch (SQLException e) {e.printStackTrace();}finally{//关闭数据库连接try {statement.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}return null;}/**专门用于插入主键自动增长的数据库表的操作,返回值为自动增长的主键值 * @author 少钦 * @param sql * @param objs * @return 插入成功的自动增长的主键,如果没有成功则返回-1 */public int add(String sql,Object[] objs){Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try {JdbcTool tool=JdbcTool.getJdbcToolInstance();conn = tool.getConnection();st = conn.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);for (int i = 0; objs != null && i < objs.length; i++) {st.setObject(i + 1, objs[i]);}st.executeUpdate();rs = st.getGeneratedKeys();if (rs.next()) {return rs.getInt(1);}elsereturn -1;} catch (Exception e) {e.printStackTrace();throw new RuntimeException("获取数据过程中出现异常" + e);} finally {JdbcTool.release(conn,st,rs);}}/**专门用来关闭数据库连接的方法,st可以PreparedStatement(Statement是pt的父类) * @author 少钦 * @param conn * @param st PreparedStatement或者Statement * @param rs */public static void release(Connection conn,Statement st,ResultSet rs){try{if(rs!=null){try{rs.close();}catch(SQLException e){throw e;}}if(st!=null){try{st.close();}catch(SQLException e){throw e;}}if(conn!=null){try{conn.close();}catch(SQLException e){throw e;}}}catch (SQLException e) {throw new RuntimeException("关闭数据库连接时发生异常!异常信息:"+e);}}public static void main(String[] args) throws Exception{System.out.println(getTableList("select * from field where field_id>?", new Object[]{10}, new Field()));}/** * 根据sql,返回对象的集合 * 这个方法的使用要求:传入的sql属于预处理的sql * args可以为null,或者是一个没有内容的Object[]数组 * object是要封装的数据类型,在每次方法返回的时候,必须要转换为你所需要的数据类型,当然,读者可以自己修改为泛型方法,那样子封装更加完美 * * bug:因为封装过程中,每次只是修改Object的内容,然后添加到集合中,所以这个集合中的所有对象都是同一个对象...不可以使用Set进行转换 * * @param args sql的参数 * @param object 要封装的类型 * * @throws SQLException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException * */public static List<Object> getTableList(String sql, Object[] args, Object object) throws SQLException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{Connection conn = getJdbcToolInstance().getConnection();PreparedStatement ps = conn.prepareStatement(sql);ResultSet rs = null;if(args == null || args.length ==0){ //没有参数rs = ps.executeQuery(); //查询}else{ //有参数for(Object obj: args){ps.setObject(1, obj);} rs = ps.executeQuery();}ResultSetMetaData rsmd = rs.getMetaData();int columnCount = rsmd.getColumnCount(); //the column of the table@SuppressWarnings("rawtypes")Class clazz = object.getClass();//获得所有的属性java.lang.reflect.Field[] fields = clazz.getDeclaredFields();String[] methodNames = new String[fields.length];//get all object methodMethod[] methods = object.getClass().getDeclaredMethods(); //获得所有的方法名for(int i=0; i<fields.length; i++){methodNames[i] = "set" + fields[i].getName().substring(0, 1).toUpperCase() + fields[i].getName().substring(1);}//封装存在的问题:因为这里每次都把参数object加入到集合中,所以这里所有的集合对象都是同一个对象 List<Object> objList = new ArrayList<Object>(); Set<Object> objSet = new HashSet<Object>(); while(rs.next()){for(int i=0; i<columnCount; i++){String methodName = methodNames[i];for(Method method: methods){if(method.getName().equalsIgnoreCase(methodName)){//设置对象的属性method.invoke(object, rs.getObject(rsmd.getColumnName(i+1)));}}objList.add(object);}} //objSet.addAll(objList); //System.out.println("the set size is " + objSet.size()); //打印的结果为1!!!!return objList;}}
//使用到的Field类对象package net.itaem.po;import java.util.HashSet;import java.util.Set;/** * * @Description:场地po类 * @operate: * @author sen * @date 2014-3-11 */public class Field implements java.io.Serializable {// Fieldsprivate int fieldId; //IDprivate int fieldTypeId; //对应的场地类型IDprivate String fieldNumber; //场地序号 /场地名称private boolean fieldStatus; //场地的状态 fieldStatus=true为开启状态 fieldStatus=false为关闭状态private String fieldPic; //场地存放图片路径private String fieldRemark; //场地备注private Set fieldParttimes = new HashSet(0); //场地对应的场地时间段// Constructors/** default constructor */public Field() {}/** minimal constructor */public Field(int fieldId) {this.fieldId = fieldId;}/** full constructor */public Field(int fieldId, int fieldTypeId, String fieldNumber,boolean fieldStatus, String fieldPic, String fieldRemark,Set fieldParttimes) {this.fieldId = fieldId;this.fieldTypeId = fieldTypeId;this.fieldNumber = fieldNumber;this.fieldStatus = fieldStatus;this.fieldPic = fieldPic;this.fieldRemark = fieldRemark;this.fieldParttimes = fieldParttimes;}public Field(int fieldId, int fieldTypeId, String fieldNumber,String fieldPic, String fieldRemark) {this.fieldId = fieldId;this.fieldTypeId = fieldTypeId;this.fieldNumber = fieldNumber;this.fieldPic = fieldPic;this.fieldRemark = fieldRemark;}public Field(int fieldTypeId, String fieldNumber,String fieldPic, String fieldRemark) {this.fieldTypeId = fieldTypeId;this.fieldNumber = fieldNumber;this.fieldPic = fieldPic;this.fieldRemark = fieldRemark;}// Property accessorspublic int getFieldId() {return this.fieldId;}public void setFieldId(int fieldId) {this.fieldId = fieldId;}public int getFieldTypeId() {return fieldTypeId;}public void setFieldTypeId(int fieldTypeId) {this.fieldTypeId = fieldTypeId;}public String getFieldNumber() {return this.fieldNumber;}public void setFieldNumber(String fieldNumber) {this.fieldNumber = fieldNumber;}public boolean getFieldStatus() {return this.fieldStatus;}public void setFieldStatus(boolean fieldStatus) {this.fieldStatus = fieldStatus;}public String getFieldPic() {return this.fieldPic;}public void setFieldPic(String fieldPic) {this.fieldPic = fieldPic;}public String getFieldRemark() {return this.fieldRemark;}public void setFieldRemark(String fieldRemark) {this.fieldRemark = fieldRemark;}public Set getFieldParttimes() {return this.fieldParttimes;}public void setFieldParttimes(Set fieldParttimes) {this.fieldParttimes = fieldParttimes;}@Overridepublic String toString() {return "Field [fieldId=" + fieldId + ", fieldTypeId=" + fieldTypeId+ ", fieldNumber=" + fieldNumber + ", fieldStatus="+ fieldStatus + ", fieldPic=" + fieldPic + ", fieldRemark="+ fieldRemark + ", fieldParttimes=" + fieldParttimes + "]";}}
0 0
- Jdbc的普通封装
- 普通的封装类CommonUtil
- JDBC的封装
- JDBC 的封装
- JDBC的封装类
- JDBC的封装
- JDBC使用方法的封装
- JDBC连接的封装
- 关于JDBC的封装
- JAVA-JDBC的封装
- JDBC的封装
- 简单的jdbc封装+servlet的封装
- 对普通对象的JSON封装
- 自己的jdbc轻封装
- JDBC的封装类构建
- JDBC 对数据库连接的封装
- java的jdbc简单封装
- 封装的JDBC工具类
- linux下汇编
- coco笔记:如何管好.net的内存
- [C#]Winform后台提交数据且获取远程接口返回的XML数据,转换成DataSet
- 移动硬盘分区后丢失数据怎么恢复
- AutoLayout详解
- Jdbc的普通封装
- x86体系结构
- 动态设置表结构方案
- Microsoft JScript 编译错误: 缺少 ';'
- 面试题目记录2
- 提交表单时过滤掉没更改的值,只POST修改过的值
- 作为面试官,告诉你们互联网公司需要什么样的人
- leftbarbuttonitem
- ubuntu12.04使用VNC实现桌面远程访问