第一节:JDBC的概述
第二节:JDBC连接数据库
第四节:使用PreparedStatement接口实现增、删、改的操作
第五节:Resultset结果集
第六节:处理大数据对象
第七节:使用CallableStatement接口调用存储过程
第八节:使用元数据分析数据库
第九节:JDBC的事务处理事务
下面是第六个部分,其他部分可以通过上面的链接访问
8.处理大数据对象
主要从下面两个方面来学习
- 处理 CLOB 数据
- 处理 BLOG 数据
大数据对象处理主要有 CLOB(characterlarge object)和 BLOB(binary large object)两种类型的字段;在 CLOB 中可以存储大字符数据对象,比如长篇小说;在 BLOB 中可以存放二进制大数据对象,比如图片,电影,音乐;
现在做准备工作。
首先学习的是CLOB字段的: 我们进行的是大字符数据的操作,所以要用到IO流的知识以及文件操作File类的知识。简单的提一下这个IO流,第一次接触是在杭州达内实习的时候,我们做捕鱼达人的小游戏,那时候用到了图片IO流,当时只是简单的掌握了图片IO流,但是并没有对IO流进行深究,下面有我最近的一个基础知识的系统性学习。
具体的知识的学习可以看我写的另一个分类,J2SE的系统性学习——IO流和File类,对于这部分的知识点就不在这里做过多的介绍了。
首先把我一开始创建的t_book这个表再增加一个列,这列的作用是文章摘要。
如图
此数据类型存储的是大字符数据。
接下来选择一个硬盘,创建一个text文本文件,可以先不放东西进去。
我在我的项目学习专用盘中创建的text文本,如图,helloWorld
这个就是路径,实在不会找的看这里,不过记住,要改成/,这里的\是错的!。
然后下面的工作就是代码方面的了
经过表的列的增加,Book类用该也增加一个属性,并且要重写构造方法。
具体的区别与前面对比看一下
package model;
import java.io.File;
/**
* 图书的实体,有图书的所有的属性
* @author Administrator
*
*/
public class Book {
private int id;
private String bookName;
private float price;
private String author;
private int bookTypeId;
private File context;
//构造方法(快捷键写的)
public Book(String bookName, float price, String author, int bookTypeId) {
super();
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
}
//重载的构造方法
public Book(int id, String bookName, float price, String author, int bookTypeId) {
super();
this.id = id;
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
}
//为第六章的学习重载构造方法
public Book(String bookName, float price, String author, int bookTypeId, File context) {
super();
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
this.context = context;
}
//下面的所有的代码都是通过快捷键实现的
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getBookTypeId() {
return bookTypeId;
}
public void setBookTypeId(int bookTypeId) {
this.bookTypeId = bookTypeId;
}
public File getContext() {
return context;
}
public void setContext(File context) {
this.context = context;
}
@Override
public String toString() {
return "Book [id=" + id + ", bookName=" + bookName + ", price=" + price + ", author=" + author + ", bookTypeId="
+ bookTypeId + "]";
}
}
新定义的一个属性是File类型的
然后还是引用前面学的,第四节的学习中的向数据库中写入数据的知识,唯一的变化是写进去一个大字符数据。
package chap6_sec01;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import model.Book;
import util.DbUtil;
public class Demo1 {
private static DbUtil dbUtil=new DbUtil();
private static int addBook(Book book) throws Exception{
Connection con=null;
con=dbUtil.getCon();//获取连接
//数据添加的sql语句,然后挖五个坑,五个坑代表表中的五个属性
String sql="insert into t_book values(null,?,?,?,?,?)";
PreparedStatement pstmt= con.prepareStatement(sql);
//下面是给五个坑填值
pstmt.setString(1, book.getBookName());
pstmt.setFloat(2, book.getPrice());
pstmt.setString(3, book.getAuthor());
pstmt.setInt(4, book.getBookTypeId());
File context=book.getContext();//获取文件
InputStream inputStream=new FileInputStream(context);//定义一个输入流
//最后一个参数是用多常给第五个坑填值
pstmt.setAsciiStream(5, inputStream, context.length());//给第五个坑填上值
//返回的值是执行sql语句之后得表受影响的数据的条数
int result=pstmt.executeUpdate();
dbUtil.close(pstmt, con);
return result;
}
public static void main(String[] args) {
File context=new File("x:/helloWorld.txt");
Book book=new Book("网易云音乐集", 20.5f, "网易云", 5, context);
try {
int result = addBook(book);
System.out.println("信息添加成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("信息添加失败");
}
}
}
看一下变化:
- IO流的引入,在main函数中获取text文本中的东西,然后传到addBook函数中去。
- addBook函数中引入了IO流和File类的知识,并且将SQL语句多挖了一个坑,将最后一个坑的数据写进去,因为是大字符类型的数据,多以我们写的时候要传写进的数据的长度,这样能合理的应用存储的空间,也能解决定义的死的空间不够用的问题。
执行结果
为什么插入的信息context的部分是空的呢?因为我创建text文本的时候,没有写东西进去,所以我们只要在text文本中写进东西,再执行一次就能看到效果了。
简单的写点东西进去
再运行代码之后查看数据库
但是值得注意的是,文本文件中存汉子执行代码是不被允许执行的,我写进去的都是按照英文的键盘输入的。longtext不支持汉语文本。
上面是插入到数据库,下面学习怎么的读取数据库中的大字符类型的数据。
先看一下我写完了的效果吧
跟上面的对比可以看到我们是正确的读取的,这里是从数据库中读取的,不是从text文本文件中读的。
下面看代码:
package chap6_sec01;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import model.Book;
import util.DbUtil;
public class Demo1 {
private static DbUtil dbUtil=new DbUtil();
private static int addBook(Book book) throws Exception{
Connection con=null;
con=dbUtil.getCon();//获取连接
//数据添加的sql语句,然后挖五个坑,五个坑代表表中的五个属性
String sql="insert into t_book values(null,?,?,?,?,?)";
PreparedStatement pstmt= con.prepareStatement(sql);
//下面是给五个坑填值
pstmt.setString(1, book.getBookName());
pstmt.setFloat(2, book.getPrice());
pstmt.setString(3, book.getAuthor());
pstmt.setInt(4, book.getBookTypeId());
File context=book.getContext();//获取文件
InputStream inputStream=new FileInputStream(context);//定义一个输入流
//最后一个参数是用多常给第五个坑填值
pstmt.setAsciiStream(5, inputStream, context.length());//给第五个坑填上值
//返回的值是执行sql语句之后得表受影响的数据的条数
int result=pstmt.executeUpdate();
dbUtil.close(pstmt, con);
return result;
}
public static void getBook(int id)throws Exception{
Connection con=dbUtil.getCon();
String sql="select * from t_book where id=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, id);
//用到的是第五节的结果集的学习
ResultSet rs=pstmt.executeQuery();
if(rs.next()){
String bookName=rs.getString("bookName");
Float price=rs.getFloat("price");
String author=rs.getString("author");
int bookTypeId=rs.getInt("bookTypeId");
Clob c=rs.getClob("context");
String context=c.getSubString(1, (int)c.length());
System.out.println("图书名称:"+bookName);
System.out.println("图书价格:"+price);
System.out.println("图书作者:"+author);
System.out.println("图书分类:"+bookTypeId);
System.out.println("图书描述:"+context);
}
dbUtil.close(pstmt, con);//关闭相关的操作和连接
}
public static void main(String[] args) throws Exception {
/*File context=new File("x:/helloWorld.txt");
Book book=new Book("网易云音乐集", 20.5f, "网易云", 5, context);
try {
int result = addBook(book);
System.out.println("信息添加成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("信息添加失败");
}*/
getBook(6);
}
}
具体看getBook的函数,其他的和上面是一样的,我就是懒的注释,,,
然后根据这个,我们可以读取数据库中的id=6的所有的数据。
还是老样子,为什么通过id进行查询,因为这里的id是唯一的,id是主键,所以查询的结果也是唯一性的,我们只能查询一条数据的所有信息。
上面用到了Clob,这个我看这篇文章学习了一下,JAVA处理Clob大对象,这里也可以用IO流进行处理,但是很麻烦,然后直接用这个封装好的Clob就行了。
========================================================================================
下面学习的是BLOG部分的,主要是对图片,电影,音乐的存储,把这些信息存到数据库中,本质是处理二进制的内容。
做准备工作,上面的加了书的简介,下面可以给这本书加上插图,所以老样子,我要去改变数据库的表,为表再增加一列,然后改变实体Book,在其中再增加一个属性。
网上查了一下这个存二进制的东西的限制大小,能存好几个G,所以完全放心的,已经足够用了
改变表,增加新的一列。
然后在X盘中放一个图片。
最近迷上大Q宝贝了,,,将就看一下吧,还蛮可爱的。
然后我们看代码,,,
老样子,先改Book类,增加新的属性,重写构造方法。
package model;
import java.io.File;
/**
* 图书的实体,有图书的所有的属性
* @author Administrator
*
*/
public class Book {
private int id;
private String bookName;
private float price;
private String author;
private int bookTypeId;
private File context;
private File pic;
//构造方法(快捷键写的)
public Book(String bookName, float price, String author, int bookTypeId) {
super();
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
}
//重载的构造方法
public Book(int id, String bookName, float price, String author, int bookTypeId) {
super();
this.id = id;
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
}
//为第六章的学习重载构造方法
public Book(String bookName, float price, String author, int bookTypeId, File context) {
super();
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
this.context = context;
}
//BLOG部分的重载
public Book(String bookName, float price, String author, int bookTypeId, File context, File pic) {
super();
this.bookName = bookName;
this.price = price;
this.author = author;
this.bookTypeId = bookTypeId;
this.context = context;
this.pic = pic;
}
//下面的所有的代码都是通过快捷键实现的
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getBookTypeId() {
return bookTypeId;
}
public void setBookTypeId(int bookTypeId) {
this.bookTypeId = bookTypeId;
}
public File getContext() {
return context;
}
public void setContext(File context) {
this.context = context;
}
public File getPic() {
return pic;
}
public void setPic(File pic) {
this.pic = pic;
}
@Override
public String toString() {
return "Book [id=" + id + ", bookName=" + bookName + ", price=" + price + ", author=" + author + ", bookTypeId="
+ bookTypeId + "]";
}
}
有了新增的属性,新的构造方法以及set和get,现在我们就可以写主要的代码了,直接copy上面的学习用的代码 ,稍微改一下
package chap6_sec02;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import model.Book;
import util.DbUtil;
public class Demo1 {
private static DbUtil dbUtil=new DbUtil();
private static int addBook(Book book) throws Exception{
Connection con=null;
con=dbUtil.getCon();//获取连接
//数据添加的sql语句,然后挖五个坑,五个坑代表表中的五个属性
String sql="insert into t_book values(null,?,?,?,?,?,?)";
PreparedStatement pstmt= con.prepareStatement(sql);
//下面是给五个坑填值
pstmt.setString(1, book.getBookName());
pstmt.setFloat(2, book.getPrice());
pstmt.setString(3, book.getAuthor());
pstmt.setInt(4, book.getBookTypeId());
File context=book.getContext();//获取文件
InputStream inputStream=new FileInputStream(context);//定义一个输入流
//最后一个参数是用多常给第五个坑填值
pstmt.setAsciiStream(5, inputStream, context.length());//给第五个坑填上值
File pic=book.getPic();
InputStream inputStream2=new FileInputStream(pic);//定义一个输入流
pstmt.setBinaryStream(6, inputStream2, pic.length());
//返回的值是执行sql语句之后得表受影响的数据的条数
int result=pstmt.executeUpdate();
dbUtil.close(pstmt, con);
return result;
}
public static void getBook(int id)throws Exception{
Connection con=dbUtil.getCon();
String sql="select * from t_book where id=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, id);
//用到的是第五节的结果集的学习
ResultSet rs=pstmt.executeQuery();
if(rs.next()){
String bookName=rs.getString("bookName");
Float price=rs.getFloat("price");
String author=rs.getString("author");
int bookTypeId=rs.getInt("bookTypeId");
Clob c=rs.getClob("context");
String context=c.getSubString(1, (int)c.length());
System.out.println("图书名称:"+bookName);
System.out.println("图书价格:"+price);
System.out.println("图书作者:"+author);
System.out.println("图书分类:"+bookTypeId);
System.out.println("图书描述:"+context);
}
dbUtil.close(pstmt, con);//关闭相关的操作和连接
}
public static void main(String[] args) throws Exception {
File context=new File("x:/helloWorld.txt");
File pic=new File("x:/pic.jpg");
Book book=new Book("网易云音乐集", 20.5f, "网易云", 5, context,pic);
try {
int result = addBook(book);
System.out.println("信息添加成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("信息添加失败");
}
}
}
主要改变在addBook这个类中,然后在main函数中写了一个新的File,作为对图片的引入。
变动如下,在addBook中的变动
在main中的变动
执行之后去数据库中查看,效果如下,还是能看到我们可爱的大Q宝的。
老样子,进去了是进去了,怎么把它从数据库中弄出来呢?
下面看代码
package chap6_sec02;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import model.Book;
import util.DbUtil;
public class Demo1 {
private static DbUtil dbUtil=new DbUtil();
private static int addBook(Book book) throws Exception{
Connection con=null;
con=dbUtil.getCon();//获取连接
//数据添加的sql语句,然后挖五个坑,五个坑代表表中的五个属性
String sql="insert into t_book values(null,?,?,?,?,?,?)";
PreparedStatement pstmt= con.prepareStatement(sql);
//下面是给五个坑填值
pstmt.setString(1, book.getBookName());
pstmt.setFloat(2, book.getPrice());
pstmt.setString(3, book.getAuthor());
pstmt.setInt(4, book.getBookTypeId());
File context=book.getContext();//获取文件
InputStream inputStream=new FileInputStream(context);//定义一个输入流
//最后一个参数是用多常给第五个坑填值
pstmt.setAsciiStream(5, inputStream, context.length());//给第五个坑填上值
File pic=book.getPic();
InputStream inputStream2=new FileInputStream(pic);//定义一个输入流
pstmt.setBinaryStream(6, inputStream2, pic.length());
//返回的值是执行sql语句之后得表受影响的数据的条数
int result=pstmt.executeUpdate();
dbUtil.close(pstmt, con);
return result;
}
public static void getBook(int id)throws Exception{
Connection con=dbUtil.getCon();
String sql="select * from t_book where id=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, id);
//用到的是第五节的结果集的学习
ResultSet rs=pstmt.executeQuery();
if(rs.next()){
String bookName=rs.getString("bookName");
Float price=rs.getFloat("price");
String author=rs.getString("author");
int bookTypeId=rs.getInt("bookTypeId");
Clob c=rs.getClob("context");
String context=c.getSubString(1, (int)c.length());
Blob b=rs.getBlob("pic");
/*由于开发工具是没法显示图片的
*所以把从数据库中获得的数据存到某个硬盘中
*/
//定义一个输出流
FileOutputStream out=new FileOutputStream(new File("e:/pic2.jpg"));
out.write(b.getBytes(1, (int)b.length()));
out.close();//用完就关闭
System.out.println("图书名称:"+bookName);
System.out.println("图书价格:"+price);
System.out.println("图书作者:"+author);
System.out.println("图书分类:"+bookTypeId);
System.out.println("图书描述:"+context);
}
dbUtil.close(pstmt, con);//关闭相关的操作和连接
}
public static void main(String[] args) throws Exception {
/*File context=new File("x:/helloWorld.txt");
File pic=new File("x:/pic.jpg");
Book book=new Book("网易云音乐集", 20.5f, "网易云", 5, context,pic);
try {
int result = addBook(book);
System.out.println("信息添加成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("信息添加失败");
}*/
getBook(7);
}
}
主要变动如下:
在getBook中新增
在main函数中注释点addBook函数的使用,然后调用getBook函数
id=7是数据库中的,看数据库
然后在上面的写的有输出流,把从数据库中的数据写道E盘中存储,下面是执行代码之后的效果。
本次的学习就在这里结束了,注意BLOG部分的学习,我们操作的都是二进制的数据,学习过计算机组成的都知道,计算机中存储的数据都是二进制的形式,8进制和16进制只是为了方面我们人类对数据的处理,所以我们在计算的时候,移位运算比正常的扩大缩小的运算要看,这个本质上说是不用转化成二进制来进行计算的,还有ClOB部分的学习的时候,是对大字符类型的数据进行处理,不论是ClOB还是BLOG ,我们在数据库中定义数据类型的时候,都不用写数据的长度。
需要学习的时候用到的数据库和所有的源代码,请去百度网盘提取
链接:https://pan.baidu.com/s/1wDL_aFCPQ9WAZ_vSy6UVdg
提取码:hime