JDBC

来源:互联网 发布:北京ktv 知乎 编辑:程序博客网 时间:2024/06/05 00:11
JDBC

一、数据库驱动的概念、JDBC
 数据库厂商提供的用来操作数据库用的jar包就是数据库驱动。各个厂商如果提供各自的数据库驱动的话会导致开发人员学习成本太高,所以sun公司提供了一套数据库驱动应该遵循的接口规范,这套规范就叫做JDBC,本质上是很多的接口。
由于所有的数据库驱动都遵循JDBC规范,我们在学习和使用数据库时只要学习JDBC中的接口就可以了。

二、JDBC快速入门
 *在数据库中建立好表
 *在程序中导入数据库驱动包

 1.注册数据库驱动
 DriverManager.registerDriver(new Driver());//缺点一:观察mysqlDriver源码发现此方法导致了数据库驱动被注册了两次。缺点二:整个程序域mysql数据库驱动绑定增加了耦合性
 推荐方式:Class.forName(“com.mysql.jdbc.Driver”); //优点:采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高。


 2.获取连接
 DriverManager.getConnection(url, user, password);

 数据库url:URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库。
 ~数据库url的写法:
  Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
  SqlServer—jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
  MySql—jdbc:mysql://localhost:3306/sid
 ~url可以接的参数:
  user、password
  useUnicode=true&characterEncoding=UTF-8

 3.获取传输器
  createStatement():创建向数据库发送sql的statement对象。
  prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。

 4.利用传输器执行sql语句获取结果集
  executeQuery(String sql) :用于向数据发送查询语句。
  executeUpdate(String sql):用于向数据库发送insert、update或delete语句
  execute(String sql):用于向数据库发送任意sql语句

 5.遍历结果集取出结构
  ResultSet以表的样式在内存中保存了查询结果,其中还维护了一个游标,最开始的时候游标在第一行之前,每调用一次next()方法就试图下移一行,如果移动成功返回true;
  ResultSet还提供了很多个Get方法,用来获取查询结果中的不同类型的数据
  除了next方法,还有以下方法可以用来遍历结果集:
   next():移动到下一行
   Previous():移动到前一行
   absolute(int row):移动到指定行
   beforeFirst():移动resultSet的最前面。
   afterLast() :移动到resultSet的最后面。

 6.释放资源
  conn是一个有限的资源,用完立即要释放表
  stat占用内存,所以使用完后也要释放
  rs占用内存,所以使用完后也要释放
 *释放时后创建的先释放
  if(rs != null){   try {    rs.close();   } catch (SQLException e) {    e.printStackTrace();   } finally{    rs = null;   }  }  if(stat != null){   try {    stat.close();   } catch (SQLException e) {    e.printStackTrace();   } finally{    stat = null;   }  }  if(conn != null){   try {    conn.close();   } catch (SQLException e) {    e.printStackTrace();   } finally{    conn = null;   }  }


  
三、PreparedStatement
 1.Sql注入:由于jdbc程序在执行的过程中sql语句在拼装时使用了由页面传入参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生变化,这种攻击方式就叫做sql注入,参考用户注册登录案例。
 2.PreparedStatement是Statement的孩子,不同的是,PreparedStatement使用预编译机制,在创建PreparedStatement对象时就需要将sql语句传入,传入的过程中参数要用?替代,这个过程回导致传入的sql被进行预编译,然后再调用PreparedStatement的setXXX将参数设置上去,由于sql语句已经经过了预编译,再传入特殊值也不会起作用了。
 3.PreparedStatement使用了预编译机制,sql语句在执行的过程中效率比Statement要高。
 
 
 
四、大数据

 1.mysql数据库也可以直接在数据库中保存大文本和大二进制数据,
  Text
  TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)
  Blob
  TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

 2.JDBC去操作大文本:

  ~插入大文本:
   ps = conn.prepareStatement("insert into Demo2Text values(null,?,?)");
   ps.setString(1, "钢铁是怎样练成");
   File file = new File("1.txt");
   ps.setCharacterStream(2, new FileReader(file), (int) file.length());

    //1.Exception in thread "main" java.lang.AbstractMethodError: com.mysql.jdbc.PreparedStatement.setCharacterStream(ILjava/io/Reader;J)V
     //ps.setCharacterStream(2, new FileReader(file), file.length());第三个参数是long型的是从1.6才开始支持的,驱动里还没有开始支持。
     //解决方案:ps.setCharacterStream(2, new FileReader(file), (int)file.length());

    //2.Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
     //文件大小过大,导致PreparedStatement中数据多大占用内存,内存溢出
     //-Xms256M-Xmx256M 修改Java虚拟机启动内存大小

    //3.com.mysql.jdbc.PacketTooBigException: Packet for query is too large (10886466 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.
     //数据库连接传输用的包不够大,传输大文本时报此错误
     //在my.ini中配置max_allowed_packet指定包的大小

   ~查询大文本:
    Reader rd = rs.getCharacterStream("content");

  3.JDBC操作大二进制
  ~插入:
   ps = conn.prepareStatement("insert into Demo3Blob values(null,?,?)");
   ps.setString(1, "梦想的力量");
   File file = new File("1.mp3");
   ps.setBinaryStream(2, new FileInputStream(file), (int) file.length());   
  ~查询:
   InputStream in = rs.getBinaryStream("content");

五、JDBC元数据API

元数据:数据库、表、列的定义信息。

(1)Connection.getMetaData():获取代表DataBase元数据的DataBaseMetaData对象
    DATaBaseMetaData对象
        getURL():返回一个String类对象,代表数据库的URL。
        getUserName():返回连接当前数据库管理系统的用户名。
        getDriverName():返回驱动驱动程序的名称。
        getPrimaryKeys(String catalog, String schema, String table):返回指定表主键的结果集
        getTables()

(2)PreparedStatement . getParameterMetaData() :获得代表PreparedStatement元数据的ParameterMetaData对象。
        Select * from user where name=? And password=?
    ParameterMetaData对象
        getParameterCount() :获得指定参数的个数
        getParameterTypeName(int param) :获得指定参数的sql类型

        *getParameterType异常处理:
               Parameter metadata not available for the given statement
               url后面拼接参数
               ?generateSimpleParameterMetadata=true

(3)ResultSet. getMetaData() :获得代表ResultSet对象元数据的ResultSetMetaData对象。
    ResultSetMetaData对象
        getColumnCount() :返回resultset对象的列数
        getColumnName(int column) :获得指定列的名称
        getColumnTypeName(int column):获得指定列的类型
原创粉丝点击