JDBC是java程序操作数据库的API
一 JDBC连接数据库的过程
(1) 注册数据库驱动
Class.forName("com.mysal.jdbc.Dirver") //加载数据库驱动,注册数据库驱动管理器
(2)构建数据库连接URL
String url="jdbc:mysql://localhost:3306/test"
url都符合一个基本的格式,即“JDBC 协议+IP地址或域名+端口+数据库名称"
(3) 获取Connection对象
Connection con=DriverMannager.getConnection(url,username,password); //闯将Connection连接
二 JDBC API
(1) Connection接口
获得数据库的连接对象
(2)DriverManager类
主要作用于用户及驱动程序之间,它是JDBC中的管理层
(3) Statement接口
这个是实现对sql语句的管理
(4)PreparedStatement接口
这个接口是对Statement的扩充,应为对于sql语句中的有些操作是要传参数的,这能用PrePareStatement
有一点个值得注意的是:使用PreparedStatement对象对sql语句的占位符参数赋值,其参数的下标值不是0,而是1
使用这个还可以防止注入攻击
(5) ResultSet接口
执行sql语句的查询语句返回的结果集;
这里也有要强调的是:ResultSet集合中第一行数据之前与最后一行数据之后都存在一个位置,而默认情况下光标位于第一行数据之前
所以在执行循环判断语句就会出项这样一种情况:while( rs,next()) 等于是将光标移到了第一条数据的位置
三 JDBC操作数据库
(1) 实现批处理
我觉得主要是讲sql语句以及它们的参数分别以对象的形式进行处理
当然在调用PreparedStatement的executebatch() 而不是调用execute()方法或executeUpdate()
(2) 调用存储过程
提供了CallableStatement
语法: {call <procedure-name>[(<arg1>,<arg2>,...)]}
四 案例
DBhelper
package com.yc.test1.dao; import java.io.IOException; 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.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.yc.test1.utils.LogUtil; public class DBHelper { //让静态块保证数据库的驱动只加载一次 static{ try{ //因为只有一条语句需要调用Myproperties ,可以直接.getInstance(). 来直接调用 Class.forName(MyProperties.getInstance().getProperty("driverclassname")); }catch(ClassNotFoundException e){ LogUtil.log.error(e.toString()); e.printStackTrace(); }catch(IOException e){ LogUtil.log.error(e.toString()); e.printStackTrace(); } } //获取与数据库的连接 public Connection getCon() throws SQLException, IOException{ //因为有三句语句需要Myproperties,所以getInstance 它,节省语句 MyProperties mp=MyProperties.getInstance(); Connection con=DriverManager.getConnection(mp.getProperty("url"),mp.getProperty("username"),mp.getProperty("password")); return con; } //查询数据 public List<Map<String,String>> findAll(String sql,List<Object>params) throws SQLException, IOException{ Connection con=getCon(); PreparedStatement pstmt=con.prepareStatement(sql); setParams(pstmt,params); // 得到结果集 ResultSet rs=pstmt.executeQuery(); //取出所有的列名,存到list中 //从结果集中取出列名 ResultSetMetaData rsmd=rs.getMetaData(); //取出列数 int columnCount=rsmd.getColumnCount(); List<String>cnlist=new ArrayList<String>(); for(int i=1;i<=columnCount;i++){ cnlist.add(rsmd.getColumnName(i)); } List<Map<String,String>>list=new ArrayList<Map<String,String>>(); //取出表中的数据 while(rs.next()){ Map<String,String>map=new HashMap<String,String>(); //循环cnlist中所有的列名,再根据这个列名从rs 中取数据 for(String cn:cnlist){ map.put(cn, rs.getString(cn)); } list.add(map); } closeAll(pstmt,con,rs); return list; } //查询聚合函数的方法: count avg max min public double findDouble(String sql,List<Object>params) throws SQLException, IOException{ double result=0; Connection con=getCon(); PreparedStatement pstmt=con.prepareStatement(sql); setParams(pstmt,params); //得到结果集 ResultSet rs=pstmt.executeQuery(); if(rs.next()){ result=rs.getDouble(1); } closeAll(pstmt,con,rs); return result; } //封装增删改 public int doUpdate(String sql,List<Object>params) throws SQLException, IOException{ Connection con=getCon(); PreparedStatement pstmt=con.prepareStatement(sql); setParams(pstmt,params); int result=pstmt.executeUpdate(); closeAll(pstmt,con,null); return result; } //封装事务的增删改 public void doUpdate(List<String> sqls,List<List<Object>>listparams) throws SQLException, IOException{ Connection con=getCon(); PreparedStatement pstmt=null; //关闭隐式事务提交(一句sql语句提交一次) con.setAutoCommit(false); try{ if(sqls!=null&&sqls.size()>0){ for(int i =0 ; i<sqls.size();i++){ String sql=sqls.get(i);//取出每条sql 语句 pstmt=con.prepareStatement(sql); setParams(pstmt,listparams.get(i)); pstmt.executeUpdate(); } } con.commit();//提交事务 }catch(Exception e){ if(con!=null){ con.rollback(); } LogUtil.log.error(e.toString()); }finally{ con.setAutoCommit(true);//再次恢复事务为隐式事务 closeAll(pstmt,con,null); } } //设置sql语句当中的参数,如果有的话 private void setParams(PreparedStatement pstmt, List<Object> params) throws SQLException { if(params!=null&& params.size()>0){ for(int i=1;i<=params.size();i++){ pstmt.setObject(i, params.get(i-1)); } } } //关闭连接 private void closeAll(PreparedStatement pstmt,Connection con,ResultSet rs) throws SQLException{ if(rs!=null){ rs.close(); } if(pstmt!=null){ pstmt.close(); } if(con!=null){ con.close(); } } public List<Map<String, String>> find(String sql, List<Object> params) throws SQLException, IOException { List<Map<String,String>> list=new ArrayList<Map<String,String>>(); Connection con=getCon(); PreparedStatement pstmt=con.prepareStatement(sql); setParams(pstmt,params); ResultSet rs=pstmt.executeQuery(); List<String> cnames=new ArrayList<String>(); ResultSetMetaData rsmd=rs.getMetaData(); for(int i=0;i<rsmd.getColumnCount();i++){ cnames.add(rsmd.getColumnName(i+1)); } while(rs.next()){ Map<String,String>map =new HashMap<String,String>(); for(String cn:cnames){ String value=rs.getString(cn); map.put(cn, value); } list.add(map); } closeAll(pstmt,con,rs); return list; } }
MyProperties
package com.net.dao; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class MyProperties extends Properties { private static MyProperties myproperties; //将这个类的构造方法设为私有,这样这个类就不能多次实例化了 private MyProperties() throws IOException { InputStream iis = MyProperties.class.getClassLoader().getResourceAsStream("db.properties"); super.load(iis); } //对外提供一个方法来猎取唯一的一个实例 public static MyProperties getInstance() throws IOException { if ( myproperties == null) { myproperties = new MyProperties(); } return myproperties; } }
db.properties
username=scott password=a driveclass=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@localhost:1521:orcl