这是我JDBC的第一篇

http://blog.csdn.net/hon_3y/article/details/53535798


1.PreparedStatement对象

PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单

  1. Statement对象编译SQL语句时,如果SQL语句有变量,就需要使用分隔符来隔开,如果变量非常多,就会使SQL变得非常复杂。PreparedStatement可以使用占位符,简化sql的编写
  2. Statement会频繁编译SQL。PreparedStatement可对SQL进行预编译,提高效率,预编译的SQL存储在PreparedStatement对象中
  3. PreparedStatement防止SQL注入。【Statement通过分隔符’++’,编写永等式,可以不需要密码就进入数据库】

//模拟查询id为2的信息
String id = "2"; Connection connection = UtilsDemo.getConnection(); String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement preparedStatement = connection.preparedStatement(sql); //第一个参数表示第几个占位符【也就是?号】,第二个参数表示值是多少
preparedStatement.setString(1,id); ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) {
System.out.println(resultSet.getString("name"));
} //释放资源
UtilsDemo.release(connection, preparedStatement, resultSet);

2.批处理

当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条发送执行,采用批处理以提升执行效率

批处理有两种方式:

  1. Statement
  2. PreparedStatement

通过executeBath()方法批量处理执行SQL语句,返回一个int[]数组,该数组代表各句SQL的返回值

以下代码是以Statement方式实现批处理


/*
* Statement执行批处理
*
* 优点:
* 可以向数据库发送不同的SQL语句
* 缺点:
* SQL没有预编译
* 仅参数不同的SQL,需要重复写多条SQL
* */
Connection connection = UtilsDemo.getConnection(); Statement statement = connection.createStatement();
String sql1 = "UPDATE users SET name='zhongfucheng' WHERE id='3'";
String sql2 = "INSERT INTO users (id, name, password, email, birthday)" +
" VALUES('5','nihao','123','ss@qq.com','1995-12-1')"; //将sql添加到批处理
statement.addBatch(sql1);
statement.addBatch(sql2); //执行批处理
statement.executeBatch(); //清空批处理的sql
statement.clearBatch(); UtilsDemo.release(connection, statement, null);

以下方式以PreparedStatement方式实现批处理


/*
* PreparedStatement批处理
* 优点:
* SQL语句预编译了
* 对于同一种类型的SQL语句,不用编写很多条
* 缺点:
* 不能发送不同类型的SQL语句
*
* */
Connection connection = UtilsDemo.getConnection(); String sql = "INSERT INTO test(id,name) VALUES (?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 1; i <= 205; i++) {
preparedStatement.setInt(1, i);
preparedStatement.setString(2, (i + "zhongfucheng")); //添加到批处理中
preparedStatement.addBatch(); if (i %2 ==100) { //执行批处理
preparedStatement.executeBatch(); //清空批处理【如果数据量太大,所有数据存入批处理,内存肯定溢出】
preparedStatement.clearBatch();
} }
//不是所有的%2==100,剩下的再执行一次批处理
preparedStatement.executeBatch(); //再清空
preparedStatement.clearBatch(); UtilsDemo.release(connection, preparedStatement, null);

3.处理大文本和二进制数据

clob和blob

  • clob用于存储大文本
  • blob用于存储二进制数据

MYSQL

MySQL存储大文本是用Test【代替clob】,Test又分为4类

  • TINYTEXT
  • TEXT
  • MEDIUMTEXT
  • LONGTEXT

同理blob也有这4类


下面用JDBC连接MySQL数据库去操作大文本数据和二进制数据



/*
*用JDBC操作MySQL数据库去操作大文本数据
*
*setCharacterStream(int parameterIndex,java.io.Reader reader,long length)
*第二个参数接收的是一个流对象,因为大文本不应该用String来接收,String太大会导致内存溢出
*第三个参数接收的是文件的大小
*
* */
public class Demo5 { @Test
public void add() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
connection = JdbcUtils.getConnection();
String sql = "INSERT INTO test2 (bigTest) VALUES(?) ";
preparedStatement = connection.prepareStatement(sql); //获取到文件的路径
String path = Demo5.class.getClassLoader().getResource("BigTest").getPath();
File file = new File(path);
FileReader fileReader = new FileReader(file); //第三个参数,由于测试的Mysql版本过低,所以只能用int类型的。高版本的不需要进行强转
preparedStatement.setCharacterStream(1, fileReader, (int) file.length()); if (preparedStatement.executeUpdate() > 0) {
System.out.println("插入成功");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, null);
} } /*
* 读取大文本数据,通过ResultSet中的getCharacterStream()获取流对象数据
*
* */
@Test
public void read() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = JdbcUtils.getConnection();
String sql = "SELECT * FROM test2";
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { Reader reader = resultSet.getCharacterStream("bigTest"); FileWriter fileWriter = new FileWriter("d:\\abc.txt");
char[] chars = new char[1024];
int len = 0;
while ((len = reader.read(chars)) != -1) {
fileWriter.write(chars, 0, len);
fileWriter.flush();
}
fileWriter.close();
reader.close(); }
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, resultSet);
} }


/*
* 使用JDBC连接MYsql数据库操作二进制数据
* 如果我们要用数据库存储一个大视频的时候,数据库是存储不到的。
* 需要设置max_allowed_packet,一般我们不使用数据库去存储一个视频
* */
public class Demo6 { @Test
public void add() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
connection = JdbcUtils.getConnection();
String sql = "INSERT INTO test3 (blobtest) VALUES(?)";
preparedStatement = connection.prepareStatement(sql); //获取文件的路径和文件对象
String path = Demo6.class.getClassLoader().getResource("1.wmv").getPath();
File file = new File(path); //调用方法
preparedStatement.setBinaryStream(1, new FileInputStream(path), (int)file.length()); if (preparedStatement.executeUpdate() > 0) { System.out.println("添加成功");
} } catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, null);
} } @Test
public void read() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
connection = JdbcUtils.getConnection();
String sql = "SELECT * FROM test3";
preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); //如果读取到数据,就把数据写到磁盘下
if (resultSet.next()) {
InputStream inputStream = resultSet.getBinaryStream("blobtest");
FileOutputStream fileOutputStream = new FileOutputStream("d:\\aa.jpg"); int len = 0;
byte[] bytes = new byte[1024];
while ((len = inputStream.read(bytes)) > 0) { fileOutputStream.write(bytes, 0, len); }
fileOutputStream.close();
inputStream.close(); } } catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, null);
} }

Oracle

下面用JDBC连接Oracle数据库去操作大文本数据和二进制数据



//使用JDBC连接Oracle数据库操作二进制数据

/*
* 对于Oracle数据库和Mysql数据库是有所不同的。
* 1.Oracle定义了BLOB字段,但是这个字段不是真正地存储二进制数据
* 2.向这个字段存一个BLOB指针,获取到Oracle的BLOB对象,把二进制数据放到这个指针里面,指针指向BLOB字段
* 3.需要事务支持
*
* */
public class Demo7 {
@Test
public void add() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
connection = UtilsDemo.getConnection(); //开启事务
connection.setAutoCommit(false); //插入一个BLOB指针
String sql = "insert into test4(id,image) values(?,empty_blob())";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
preparedStatement.executeUpdate(); //把BLOB指针查询出来,得到BLOB对象
String sql2 = "select image from test4 where id= ? for update";
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.setInt(1, 1);
resultSet = preparedStatement.executeQuery(); if (resultSet.next()) {
//得到Blob对象--当成是Oracle的Blob,不是JDBC的,所以要强转[导的是oracle.sql.BLOB包]
BLOB blob = (BLOB) resultSet.getBlob("image"); //写入二进制数据
OutputStream outputStream = blob.getBinaryOutputStream(); //获取到读取文件读入流
InputStream inputStream = Demo7.class.getClassLoader().getResourceAsStream("01.jpg"); int len=0;
byte[] bytes = new byte[1024];
while ((len = inputStream.read(bytes)) > 0) { outputStream.write(bytes, 0, len);
}
outputStream.close();
inputStream.close();
connection.setAutoCommit(true);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
UtilsDemo.release(connection, preparedStatement, null);
} } @Test
public void find() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
connection = UtilsDemo.getConnection();
String sql = "SELECT * FROM test4 WHERE id=1"; preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { //获取到BLOB对象
BLOB blob = (BLOB) resultSet.getBlob("image"); //将数据读取到磁盘上
InputStream inputStream = blob.getBinaryStream();
FileOutputStream fileOutputStream = new FileOutputStream("d:\\zhongfucheng.jpg");
int len=0;
byte[] bytes = new byte[1024]; while ((len = inputStream.read(bytes)) > 0) { fileOutputStream.write(bytes, 0, len);
} inputStream.close();
fileOutputStream.close(); } } catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
UtilsDemo.release(connection, preparedStatement, null);
}
}
}

对于JDBC连接Oracle数据库操作CLOB数据,我就不再重复了,操作跟BLOB几乎相同


4.获取数据库的自动主键列

为什么要获取数据库的自动主键列数据?

应用场景:

有一张老师表,一张学生表。现在来了一个新的老师,学生要跟着新老师上课。

我首先要知道老师的id编号是多少,学生才能知道跟着哪个老师学习【学生外键参照老师主键】。




    @Test
public void test() { Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
connection = JdbcUtils.getConnection(); String sql = "INSERT INTO test(name) VALUES(?)";
preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "ouzicheng"); if (preparedStatement.executeUpdate() > 0) { //获取到自动主键列的值
resultSet = preparedStatement.getGeneratedKeys(); if (resultSet.next()) {
int id = resultSet.getInt(1);
System.out.println(id);
}
} } catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, null);
}

5.调用数据库的存储过程

调用存储过程的语法:


{call <procedure-name>[(<arg1>,<arg2>, ...)]}

调用函数的语法:


{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}

如果是Output类型的,那么在JDBC调用的时候是要注册的。如下代码所示:



/*
jdbc调用存储过程 delimiter $$
CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam varchar(255))
BEGIN
SELECT CONCAT('zyxw---', inputParam) into inOutParam;
END $$
delimiter ;
*/
//我们在JDBC调用存储过程,就像在调用方法一样
public class Demo9 { public static void main(String[] args) {
Connection connection = null;
CallableStatement callableStatement = null; try {
connection = JdbcUtils.getConnection(); callableStatement = connection.prepareCall("{call demoSp(?,?)}"); callableStatement.setString(1, "nihaoa"); //注册第2个参数,类型是VARCHAR
callableStatement.registerOutParameter(2, Types.VARCHAR);
callableStatement.execute(); //获取传出参数[获取存储过程里的值]
String result = callableStatement.getString(2);
System.out.println(result); } catch (Exception e) {
e.printStackTrace();
}finally {
try {
connection.close();
callableStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
} }

参考资料:



----------------------------------------------------------------------------------过程

#修改mysql语句的结果符为//
mysql > delimiter // #定义一个过程,获取users表总记录数,将10设置到变量count中
create procedure simpleproc(out count int)
begin
select count(id) into count from users;
end
// #修改mysql语句的结果符为;
mysql > delimiter ; #调用过程,将结果覆给变量a,@是定义变量的符号
call simpleproc(@a); #显示变量a的值
select @a; //以下是Java调用Mysql的过程
String sql = "{call simpleproc(?)}";
Connection conn = JdbcUtil.getConnection();
CallableStatement cstmt = conn.prepareCall(sql);
cstmt.registerOutParameter(1,Types.INTEGER);
cstmt.execute();
Integer count = cstmt.getInt(1);
System.out.println("共有" + count + "人"); ----------------------------------------------------------------------------------函数 #修改mysql语句的结果符为//
mysql > delimiter // #定义一个函数,完成字符串拼接
create function hello( s char(20) ) returns char(50)
return concat('hello,',s,'!');
// #修改mysql语句的结果符为;
mysql > delimiter ; #调用函数
select hello('world'); //以下是Java调用Mysql的函数
String sql = "{? = call hello(?)}";
Connection conn = JdbcUtil.getConnection();
CallableStatement cstmt = conn.prepareCall(sql);
cstmt.registerOutParameter(1,Types.VARCHAR);
cstmt.setString(2,"zhaojun");
cstmt.execute();
String value = cstmt.getString(1);
System.out.println(value);
JdbcUtil.close(cstmt);
JdbcUtil.close(conn);

JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】的更多相关文章

  1. jdbc执行预处理,批处理,LOB字段处理,调用存储过程

    (1)jdbc执行预处理 PreparedStatment预备语句 eg:String sql="insert into user(id,name,birthday,money) value ...

  2. JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    1.PreparedStatement对象 PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单 Statement对象编译SQL语句时, ...

  3. 【HANA系列】【第六篇】SAP HANA XS使用JavaScript(JS)调用存储过程(Procedures)

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第六篇]SAP HANA XS ...

  4. 通过 jdbc 分析数据库中的表结构和主键外键

    文章转自:http://ivan4126.blog.163.com/blog/static/20949109220137753214811/ 在某项目中用到了 hibernate ,大家都知道 hib ...

  5. Cassandra开发入门文档第二部分(timeuuid类型、复合主键、静态字段详解)

    timeuuid类型 timeuuid具有唯一索引和日期时间的综合特性,可以与日期和时间函数联合使用,常用的关联函数: dateOf() now() minTimeuuid() and maxTime ...

  6. java核心技术第四篇之JDBC第二篇

    01.JDBC连接池_连接池的概念: 1).什么是连接池:对于多用户程序,为每个用户单独创建一个Connection,会使程序降低效率.这时我们可以创建一个"容器", 这个容器中, ...

  7. EC笔记,第二部分:5.了解C++默默编写并调用哪些函数

    5.了解C++默默编写并调用哪些函数 1.C++空类 C++会为一个空类建立以下函数 (1).默认构造函数 (2).默认拷贝构造函数 (3).析构函数 (4).赋值运算符(如果成员包含引用类型或con ...

  8. 【MySQL】selectKey获取insert后的自动主键

    <insert id="insert" parameterType="cc.mrbird.febs.energy.domain.ChatGroup"> ...

  9. linux-0.11分析:boot文件 setup.s 第二篇随笔

    boot文件 setup.s 第二篇随笔 参考 [github这个博主的][ https://github.com/sunym1993/flash-linux0.11-talk ] 中断获取光标的位置 ...

随机推荐

  1. 给出打印结果-setTimeout

    问题: 请给出打印结果: for(var i=0;i<5;i++){ setTimeout(function(){ console.log(i); },0); } 解析: 考的是setTimeo ...

  2. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(五)用户接口层之提取媒体流数据

    当RTSP客户端向RTSP服务端发送完PLAY命令后,RTSP服务端就会另外开启UDP端口(SDP协商定义的端口)发送RTP媒体流数据包.这些数据包之间会间隔一段时间(毫秒级)陆续被发送到RTSP客户 ...

  3. textarea 空格的问题

    如果textarea开始标签和结束标签中间有空格,则textarea默认有空格. <textarea name=" > </textarea> 效果图 所以,如果想去 ...

  4. [js高手之路]jquery插件开发实战-选项卡详解

    在jquery中,插件开发常见的有: 一种是为$函数本身扩展一个方法,这种是静态扩展(也叫类扩展),这种插件一般是工具方法, 还有一种是扩展在原型对象$.fn上面的,开发出来的插件是用在dom元素上面 ...

  5. form enctype参数

    application/x-www-form-urlencoded 表示在发送前编码所有字符(默认) multipart/form-data 不对字符编码.在使用包含文件上传控件的表单时,必须使用该值 ...

  6. 34、锁问题与线程queue

    上一篇随笔我们学了全局解释器锁,前面也学了互斥锁,今天学习一些与锁相关的点,例如递归锁,信号量,Event,还会学习我们已经很熟悉的队列,不过这次的队列是作为一个模块出现的. 一.同步锁 1.join ...

  7. Microsoft Azure Storage Exployer使用指南

    概述 Microsoft Azure Storage Exployer 是微软官方推荐的一款管理Azure Storage 客户端工具,客户使用完全免费.支持Windows.Mac和Linux.用户使 ...

  8. 用NETSH WINSOCK RESET命令修复网络

    之前遇到一种情况,QQ可以正常使用,浏览器无法访问网页.在CMD下ping 主机也提示超时. 最后通过NETSH WINSOCK RESET命令重置WINSOCK目录,成功修复了网络连接. Netsh ...

  9. sql primary key 约束

    PRIMARY KEY 约束唯一标识数据库表中的每条记录. 主键必须包含唯一的值. 主键列不能包含 NULL 值. 每个表都应该有一个主键,并且每个表只能有一个主键. SQL PRIMARY KEY ...

  10. .NET Core多平台开发体验[2]: Mac OS X

    除了微软自家的Windows平台, .NET Core针对Mac OS以及各种Linux(RHEL.Ubuntu.Debian.Fedora.CentOS和SUSE等)都提供了很好的支持,我们先来体验 ...