Java工具类——jdbc

来源:互联网 发布:md5解密算法 编辑:程序博客网 时间:2024/05/21 14:02

java代码中操作数据库。(本文以MySQL为例)

操作通常分6步:

1.加载数据库驱动

2.建立数据库连接对象

3.创建执行SQL的语句对象

4.执行SQL语句

5.处理结果

6.释放数据库资源


数据库厂商会实现符合自己的数据库特点的数据库驱动程序。

常见数据库产品驱动加载方式如下:

Mysql
Class.forName("com.mysql.jdbc.Driver");


Oracle
Class.forName("oracle.jdbc.driver.OracleDriver");


SQLServer
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");


实际操作:

本文使用的是MySQL,首先下载一个MySQL的jdbc的jar文件。本文使用的是mysql-connector-java-5.1.41-bin.jar(可自行官网或网络下载并导入)

封装:

private static String className,url,user,password;/** * 1.加载驱动,静态代码块,只执行一次 */static {try {// 1.1.从配置文件中初始化数据库连接参数Properties pops = new Properties();pops.load(UtilsJDBC.class.getResourceAsStream("/jdbc.properties"));className = pops.getProperty("className");url = pops.getProperty("url");user = pops.getProperty("user");password = pops.getProperty("password");// 1.2.加载驱动Class.forName(className);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}
/** * 建立连接 * @return连接对象 */private static Connection getConn() {Connection conn = null;try {conn = DriverManager.getConnection(url, user, password);} catch (SQLException e) {e.printStackTrace();}return conn;}

考虑到多人同时操作数据库的问题,于是并没有给静态参数url、user、password赋值。而是通过使用配置文件jdbc.properties来封装。然后从配置文件中取出数据初始化。


下面到了创建SQL语句对象

常用的有Statement对象和PreparedStatement对象


Statement对象通过

Statement stmt = conn.createStatement();


PreparedStatement对象通过

String sql = “select * from students where name = ? and sex = ?”;
PreparedStatement ps = conn.preparedStatement(sql);
ps.setString(1,”张三”);
ps.setString(2,”女”);
此处,参数sql可以带有占位符。


Statement对象或者PreparedStatement对象调用executeXxx()方法将SQL语句发送到数据库管理系统,数据库管理系统执行完毕之后会有结果返回,不同类型的sql语句以及不同的executeXxx()方法返回的结果都不相同,那么对结果的处理方式也不各不相同。


Statement类型语句对象的执行

boolean b = stmt.execute(sql);//执行任何sql语句

int I = stmt.executeUpdate(sql);//执行增删改SQL语句

ResultSet rs = stmt.executeQuery(sql);//执行查询语句


PreparedStatement类型语句对象的执行
boolean b = ps.execute();//执行任何类型sql语句
int I = ps.executeUpdate();//执行增删改类型sql语句
ResultSet rs = ps.executeQuery();//执行查询语句

综上,可以看出增删改,返回的是sql语句在数据库中响应的行数;而查询是返回的结果集合。所以我们可写2个封装方法来区分。

另外,

·如使用createStatement,则需要配合使用executeUpdate(sql)方法,此处传入的sql不可使用占位符;

·如使用preparedStatement(sql),则需要配合使用executeUpdate()方法,此处传入的sql可使用占位符;

  ··又需要对sql使用占位符或不使用占位符来进行区分。或者写重载方法。


此处,以使用preparedStatement(sql)为例,传入可变参数来避免重载,并优化使用占位符的操作

/** * 增删改 * @param sqlsql增删改语句,可含占位符? * @param args如使用占位符,则对占位符释义 * @return相应数据库响应行数 */static public int updata(String sql,Object...args){Connection conn = null;PreparedStatement ps=null;int rows = 0;try {conn=getConn();ps=conn.prepareStatement(sql);//逐个解释占位符,占位符索引从1计数,数组索引从0计数if(args!=null && args.length>0){for(int i=0;i<args.length;i++){ps.setObject(i+1, args[i]);}}//executeUpdate可以执行增删改语句rows = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {//关闭资源,没有结果集,传入nullclose(null,ps,conn);}if (rows>0) {System.out.println("操作成功");}else {System.out.println("操作失败");}return rows;}
/** * 查询 * 多表查询时,请使用别名来区分相同的列名 * @param sqlsql查询语句,不含占位符? * @param obj占位符释义 * @return结果集封装的list集合 */public static List<Map<String, Object>> query(String sql,Object...args) {Connection conn = null;PreparedStatement ps=null;ResultSet res=null;List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();try {conn=getConn();ps = conn.prepareStatement(sql);//如果数组不为null且长度大于0说明sql语句中有?占位符//逐个解释占位符,占位符索引从1计数,数组索引从0计数if(args!=null && args.length>0){ //1for(int i=0;i<args.length;i++){ps.setObject(i+1, args[i]);}}// //executeQuery(String sql)可以执行select语句res = ps.executeQuery();//获取结果集的元数据ResultSetMetaData resmd=res.getMetaData();//获取结果集中列的数量int count=resmd.getColumnCount();while(res.next()){Map<String, Object> rowData=new HashMap<String, Object>();//列索引从1开始for (int i = 1; i <= count; i++) {//获取每一列的列名           resmd.getColumnType();//获取类型resmd.getColumnTyoeName();//获取类型名称String cname=resmd.getColumnLabel(i);Object cvalue=res.getObject(cname);rowData.put(cname, cvalue);}list.add(rowData);}} catch (SQLException e) {e.printStackTrace();}finally{close(res, ps, conn);}return list;}

最后,关闭资源。当然,上述方法中已经在执行完SQL操作之后就调用了此方法对资源进行了关闭

/** * 关闭资源 * @param res结果集 * @param stmt语句 * @param conn连接 * @throws SQLException */private static void close(ResultSet res, Statement stmt, Connection conn){try {if (res != null) {res.close();}if (stmt != null) {stmt.close();}if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}


 在上述的查询方法中,对结果集进行了处理,把结果集放入了list集合中。

这样做的原因是,在处理结果集之前,不能关闭资源。否则就无法对结果集进行处理。

而在查询后,把结果放入list之后,就立即关闭了资源。而对查询结果的处理可以通过对list的操作来执行。

这样做符合Connection的使用原则,即尽量晚创建,尽可能早释放,因为数据库的连接很有限,如果不及时释放将导致系统崩溃










0 0