JDBC

来源:互联网 发布:2017爱情电影 知乎 编辑:程序博客网 时间:2024/04/30 14:07

一、JDBC基础

  1. JDBC全称:Java Database Connectivity(Java数据库连接)
  2. 通过JDBC,就可以实现同一种API访问不同的数据库,例如,我们的代码既可以与Oracle数据库连接,也可与MySql数据库连接,二者的区别只是使用了不同的驱动程序。
  3. JDBC的作用
    1) 建立与数据库的连接
    2) 执行SQL语句
    3) 获得sql语句的执行结果
  4. JDBC的4种常用驱动
    1) JDBC-ODBC桥:基本不用
    2) 直接将JDBC API映射成数据库特定的客户端API:性能高,但编码维护困难。
    3) 支持三层结构的JDBC访问方式,主要用于Applet阶段,通过Applet访问数据库
    4) 纯Java的,直接与数据库实例交互,该方式智能,它知道数据库使用的底层协议
    最常用的是第四种,而对性能有严格要求时,应选择第二种

二、JDBC的典型用法

  1. DriverManager:用于获取Connectoin对象
    public static synchronized Connection getConnection(String url,String user,String psw);
    可以看出,获取数据库连接是一个同步的方法。

  2. Connection:代表数据库连接对象,常用方法如下:
    1) Statement createStatement() throws Exception:获得Statement对象
    2) PreparedStatement preparedStatement(String sql):返回预编译的Statement对象
    3) CallableStatement prepareCall(String sql):返回调用存储过程的CallableStatement
    其中PreparedStatement和CallableStatement都是Statement的子类

  3. Connection的控制事务的方法
    1) Savepoint setSavepoint():创建一个事务保存点(中间点)
    2) void setTransactionIsolation(int level):设置事务隔离级别
    3) void rollback():回滚事务
    4) void rollback(Savepoint point):将事务回滚到指定的保存点
    5) void setAutoCommit(Boolean b):是否开启事务(false为开启)
    6) void commit():提交事务
    7) void setNetworkTimeout(Executor e,int milliseconds):设置数据库连接超时行为
  4. Statement:用于执行SQL语句的工具接口
    1) ResultSet executeQuery(String sql):执行查询SQL语句
    2) int executeUpdate():执行除了查询以外的其他SQL语句。执行DDL语句返回0,执行DML语句返回受影响行数
    3) boolean execute(String sql):执行任何SQL语句。如果执行SQL语句结果是ResultSet则返回true,否则返回false
    4) void closeOnCompletion():当所有依赖该Statement的ResultSet关闭时,则该Statement对象自动关闭
    通常没有必要使用execute()方法执行SQL语句,除非不清楚SQL语句类型,因为比较麻烦;一般使用比较简单的executeQuery()方法或executeUpdate()方法
  5. PreparedStatement:预编译的Statement对象
    1) 因为PreparedStatement对象已编译了SQL语句,所以它的有关执行SQL语句的方法不再需要传入SQL语句了,如executeQuery()、executeUpdate()、execute()
    2) setXxx(int index,Xxx value):给指定索引位置(占位符)传入值,如:
    setString(2,”张三”):给第二个占位符传入”张三”
    3) prearedStatement执行SQL语句的优点:
    a) 使用占位符,既避免了传参时拼接字符串,又避免了SQL注入
    b) 传参时若不知道参数类型时,可用setObject()方法
    c) 因为是预编译SQL语句(只需要传一条SQL语句就OK了),所以执行效率高
  6. ResultSet:结果集对象
    1) 通过列名或列索引获得数据
    getXxx(int index)、getXxx(String columnName)
    T getObject(int index)、getObject(String columnName)
    2) boolean absolute(int row):移动到第row行,row为负数时指倒数
    3) void beforeFirst():将记录指针移到第一行之前
    4) boolean first():将ResultSet的指针定位到首行
    5) boolean previous():定位到上一行
    6) boolean next():定位到下一行
    7) boolean last():定位到最后一行
    8) void afterLast():定位到最后一行之后
    9) void close():释放ResultSet对象
    注:ReslutSet的getString()方法可获得除Blob类型之外的任意类型类的值,因为这些类型都可以自动转换成字符串

三、JDBC编程示例与步骤

  1. 用executeQuery方法执行SQL语句:
public static void main(String[] args) throws Exception{    Class.forName(“com.mysql.jdbc.Driver”); // 加载驱动    String  url=”jdbc:mysql://127.0.0.1:3306/db”;    Connection con= DriverManager.getConnection(url,”root”,”root”);//获得数据库连接    Statement  st = con.createStatement();    ResultSet  rs = st.executeQuery(“select * from user”);    while(rs.next()){        System.out.println(rs.getInt(“id”)+”==”+rs.getString(“username”));    }}
  1. 使用execute方法时部分代码示例
Statement  st = con.createStatement();boolean  b = st.execute(“select * from user”);if(b){ // 说明执行结果是ResultSet     ResultSet  rs = st.getResult();     int  columnNum = rs.getColumnCount(); // 获得列数     while(){        for(int i=0;i<columnNum;i++){            System.out.println(rs.getString(i+1));        }    }}else{    //说明执行SQL结果不是查询,而是DDL或DML操作}
  1. 用:PreparedStatement 执行SQL语句部分代码示例
 preparedStatement  ps = conn.preparedStatement(“insert into user values(“null,?”); for(int i=0;i<100;i++){    ps.setString(1,”姓名”+i); // 给第一个占位符赋值    ps.executeUpdate();}
  1. 使用CallalbeStatement调用存储过程
CallalbeStatement cs = conn.prepareCall(“{call  add_user(?,?,?)}”); //add_user为存储过程名字cs.setInt(1,4); //给第一个占位符传参cs.setInt(2,5); //给第二个占位符传参cs.registerOutParameter(3,Types.INTEGER);// 第三个占注册成传出参数,并指定类型ex.execute();System.out.println(“执行结果是:”+cs.getInt(3));
  1. 处理Blob类型数据,即Binary Long Object(二进制长对象)
    1) 插入数据库用PreparedStatement的setBinaryStream(int index , InputStream in)方法
    2) 取出Blob数据时,用ResultSet的getBlob(int index)方法获得Blob对象,Blob对象方法:
    getBinaryStream():取出输入流
    getBytes():取出二进制流
    3) Mysql数据库的Blob类型只能存64k的内容,mediumblob类型能存16M的内容
    6.ReslutSetMetaData
    Statement st = con.createStatement();
    ResultSet rs = st.executeQuery(sql); //sql字符串省略了
    ReslutSetMetaData rsmd = rs.getMetaData();
    int columnNum = rsmd.getColumnCount(); // 列数量
    String columnName = rsmd.getColumnName(2);// 获得索引为2的列的列名
    int columnType = rsmd.getColumnType(2); // 获得索引为2的列的列类型
    虽然ReslutSetMetaData对象可准确分析出ResultSet里包含多少列,以及每列的列名和类型,但使用它会有一定的系统开销,因此建议能不用就不用。

四、RowSet

  1. RowSet接口规范类图
    这里写图片描述
    离线RowSet:Connection关闭前,可将底层的数据读取到内存中进行离线操作
    连线RowSet:程序得到ResultSet后,必须立即处理数据,否则一旦Connection关闭,再通过ResultSet去读取时会报错

  2. 通过RowSetProvider创建RowSetFactory,然后通过RowSetFactory创建各类型的RowSet
     JdbcRowSet createJdbcRowSet()
     CachedRowSet createCachedRowSet()
     WebRowSet createWebRowSet()
     JoinRowSet createJoinRowSet()
     FilteredRowSet createFilteredRowSet()

  3. 离线RowSet(CachedRowSet)的分页
     setPageSize(int pageSize):设置返回条数
     previousPage():读取上一页记录
     nextPage():读取下一页记录
     populate(ResultSet rs, int startRow):填充RowSet startRow=(pageNo-1)*pageSize+1
    示例:
.省略部分代码Statement  st = con.createStatement();ResultSet  rs = st.executeQuery(sql);RowSetFactory  f = RowSetProvider.newFactory();// 获得创建RowSet的工厂CachedRowSet  cache = f.createCachedRowSet();// 创建离线RowSetcache.setPageSize(10);  //每次取多少条cache.populate(rs,(pageNo-1)*pageSize+1) );//缓存结果,并求出从第几条开始取while(rs.next()){    //…..}

五、批量更新

  1. 批量更新,是将多个SQL语句一起提交给数据库执行(需要数据库支持)
  2. 注意事项
     批量更新时不能有select查询语句,否则程序会出错
     必须把批量操作当成单个事务,如果有一条SQL语句执行失败,则回滚到之前的状态
     MySql不支持Java8的executeLargeBatch() 和executeLargeUpdate()方法
  3. 示例
boolean  flag = con.getAutoCommit(); // 保存当前事务状态    con.setAutoCommit(false); // 开启事务    Statement  st = con.createStatement();    st.addBatch(sql1);    st.addBatch(sql2);    st.addBatch(sql3);    st.executeBatch(); // 执行批量操作    con.commit(); // 提交事务    con.setAutoCommit(flag); // 将事务恢复到之前的状态

六、使用连接池管理数据库连接

  1. 什么是连接池?
    连接池是生产并管理数据库连接的工厂
  2. 为什么需要连接池?
    数据库连接的建立和关闭都是极为耗资源的操作,频繁地打开和关闭连接,将造成系统性能低下。
  3. 连接池工作原理
    应用程序每次请求数据库连接时,都从连接池取出一个已有的空闲连接,使用完后,不会关闭连接,而是归还给连接池等待下一个请求来获取使用
  4. 两种连接池
     DBCP数据源:参见P638
     C3P0数据源:参见P639。C3P0要优于DBCP,Hibernate推荐使用C3P0
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 截关日期是假日怎么办 恒温阀冷水进水堵塞怎么办 缺氧液泵管道堵塞怎么办 货物包装大集装箱装不下怎么办 微信收藏的视频格式错误怎么办 乙方被刑拘房租未付清怎么办 房贷银行卡号弄错怎么办 社保卡号弄错了怎么办 社保名字写错了怎么办 档案和身份证年龄姓名不一样怎么办 档案年龄与身份证年龄不一样怎么办 户口本身份证和档案不一样怎么办 如果档案姓名与身份证不符怎么办 感冒吃了白参怎么办 吃辣的嗓子疼怎么办 美团客户更改地址怎么办 忘记steam的账户名称怎么办 重置手机忘了密码怎么办 sp下行短信费扣怎么办 hr公司业务员招不到人怎么办 卖房中介被房倒压房子怎么办 电脑放不了dvd光盘怎么办 股东迟迟不交齐股本金怎么办 wps转pdf就乱了怎么办 被有用分期骗了怎么办 找不到以前有用分期的账号怎么办 打工去韩国不懂韩语怎么办? 想去韩国整容没钱怎么办 专接本没接上怎么办 抄写经文写错了怎么办 在外地修车被宰怎么办 国外汇款公司名称写错了怎么办 增值税专票没有机器编码怎么办 发票右上角的编码打不全怎么办 税票名称开错了怎么办 开票名称开错了怎么办 退休党员不交党费怎么办 cad打不出来字怎么办 用cad打不出来字怎么办 打字总打错字母怎么办 mac做ppt卡住了怎么办