处理Blob类型数据:
(1)Blob(Binary long Object)是二进制长对象的意思,Blob通常用于存储大文件,典型的Blob内容是一张图片或者一个声音文件,由于他们的特殊性,必须使用特殊的方式来存储。使用Blob列可以把照片声音等文件的二进制数据保存在数据库里,并可以从数据库里恢复指定文件。
(2)如果需要将图片插入数据库,显然不能通过普通的SQL语句来完成,因为有一个关键的问题,Blob常量无法表示,所以将Blob数据插入数据库需要使用PreparedStatement。该对象有一个方法:setBinaryStream(int parameterIndex ,InputStream x) 该方法可以为指定参数传入二进制流,从而可以实现将Blob数据保存到数据库的功能。
(3)当需要从ResultSet里取出Blob数据时,可以调用ResultSet的getBlob(int columnIndex)方法,该方法将返回一个Blob对象Blob对象提供了getBinaryStream()方法获取该获取该Blob数据的输入流,也可以使用Blob对象的getBytes()方法直接取出该Blob对象封装的二进制数据
(4)实例程序:
为了把图片放入数据库,本程序先使用如下SQL语句来建立一个数据表:
create table img_table
{
img_id int auto_increment primary key,
img_name varchar(255),
#创建一个mediumblob类型的数据列,用于保存图片数据
ima_data mediumblob
};
**img_data 列使用mediumblob类型,而不是blob类型。因为MySQL数据库里的blob类型最多只能存储64kb的内容,所以使用mediumblob类型,该类型可以存储16M内容。
**下面程序可以实现图片上传,实际就是将图片保存到数据库,并在右边的列表框中显示图片的名字,当用户双击列表框中的图片名时,左边窗口将显示该图片,实质就是根据选中的ID从数据库中查找图片,并将其显示出来。
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Properties;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.filechooser.FileFilter;
import com.mysql.jdbc.Blob;
import com.mysql.jdbc.Statement;
public class BlobTest {
JFrame jf =new JFrame("图片管理程序");
//private static Connection conn;
private static PreparedStatement insert;
private static PreparedStatement query;
private static PreparedStatement queryAll;
//定义一个DefaultListModel对象
private DefaultListModel <ImageHolder> imageModel =new DefaultListModel<>();
private JList <ImageHolder> imageList = new JList<>(imageModel);
private JTextField filePath =new JTextField(26);
private JButton browserBn =new JButton("...");
private JButton uploadBn=new JButton("上传");
private JLabel imageLabel =new JLabel();
//以当前路径创建文件选择器
JFileChooser chooser=new JFileChooser(".");
//创建文件过滤器
ExtensionFileFilter filter=new ExtensionFileFilter();
static
{
try{
Properties props=new Properties();
props.load(new FileInputStream("mysql.ini"));
String driver =props.getProperty("driver");
String url =props.getProperty("url");
String user=props.getProperty("user");
String pass=props.getProperty("pass");
Class.forName(driver);
//获取数据库连接
Connection conn=DriverManager.getConnection(url, user, pass);
//创建执行插入的PrepareStatement对象,该对象执行插入后可以返回自动上生成的主键
insert =conn.prepareStatement("insert into img_table"+" values(null,?,?)", Statement.RETURN_GENERATED_KEYS);
//创建两个prepareStatement对象,用于查询指定图片,所有图片
query =conn.prepareStatement("select img_data from img_table" +"where img_id=?");
queryAll=conn.prepareStatement("select img_id,"+"img_name from img_table");
}catch (Exception e){
e.printStackTrace();
}
}
public void init() throws Exception
{
//初始化文件选择器
filter.addExtension("jpg");
filter.addExtension("jpeg");
filter.addExtension("gif");
filter.addExtension("png");
filter.setDescription("图片文件(*.jpg,*.jpeg,*.gif,*.png)");
//禁止显示 “所有文件选项”
chooser.setAcceptAllFileFilterUsed(false);
//初始化程序界面
fillListModel();
filePath.setEditable(false);
//只能单选
imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel jp=new JPanel();
jp.add(filePath);
jp.add(browserBn);
browserBn.addActionListener(event ->{
//显示对话框
int result =chooser.showDialog(jf, "浏览图片文件上传");
//如果用户选择了APPROVE按钮,即打开,保存按钮
if(result == JFileChooser.APPROVE_OPTION);
{
filePath.setText(chooser.getSelectedFile().getPath());
}
});
jp.add(uploadBn);
uploadBn.addActionListener(avt->
{
//如果上传的文本框有内容
if(filePath.getText().trim().length()>0){
//将指定的文件保存到数据库
upload(filePath.getText());
//清空文本框内容
filePath.setText("");
}
});
JPanel left=new JPanel();
left.setLayout(new BorderLayout());
left.add(new JScrollPane(imageList), BorderLayout.CENTER);
left.add(jp, BorderLayout.SOUTH);
jf.add(left);
imageList.setFixedCellWidth(160);
jf.add(new JScrollPane(imageList), BorderLayout.EAST);
imageList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
//如果鼠标双击
if(e.getClickCount()>=2){
//取出选中的List项
ImageHolder cur= (ImageHolder) imageList.getSelectedValue();
//显示选中项对应的Image
try {
showImage(cur.getId());
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
jf.setSize(620, 400);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
//——————————查找img_table填充ListModel
public void fillListModel() throws Exception{
//执行查询
ResultSet rs=queryAll.executeQuery();
//先清除所有元素
imageModel.clear();
//把查询的傲记录全部添加到ListModel中
while(rs.next()){
imageModel.addElement(new ImageHolder(rs.getInt(1),rs.getString(2)));
}
}
//将指定文件放入数据库
public void upload(String fileName) throws Exception{
//截取文件名
String imageName=fileName.substring(fileName.lastIndexOf("\\")+1,fileName.lastIndexOf('.') );
File f=new File(fileName);
InputStream is =new FileInputStream(f);
{
insert.setString(1, imageName);
insert.setBinaryStream(2, is, (int)f.length());
int affect=insert.executeUpdate();
if (affect==1){
fillListModel();
}
}
}
//根据图片ID来显示图片
public void showImage(int id) throws Exception{
//设置参数
query.setInt(1, id);
ResultSet rs=query.executeQuery();
if(rs.next()){
//取出Blob列
java.sql.Blob imgBlob=rs.getBlob(1);
//取出Blob列的数据
ImageIcon icon=new ImageIcon(imgBlob.getBytes(1L, (int)imgBlob.length()));
imageLabel.setIcon(null);
}
}
public static void main(String[] args){
new BlobTest().init();
}
//创建FileFilter的子类,用于实现文件过滤的功能
class ExtensionFileFilter extends FileFilter
{
private String description="";
private ArrayList<String> extensions =new ArrayList<>();
//自定义方法,用于添加文件扩展名
public void addExtension(String extension)
{
if(! extension.startsWith(".")){
extension="." +extension;
extensions.add(extension.toLowerCase());
}
}
//用于设置该文件过滤器的描述性文本
public void setDescription (String aDescription)
{
description=aDescription;
}
//继承FileFilter必须实现的抽象方法,判断该文件过滤器是否接受该文件
@Override
public boolean accept(File f) {
// TODO Auto-generated method stub
//如果该文件是路径,则接受该文件
if(f.isDirectory())
return true;
//将文件名转为小写(全部转化为小写后,用于忽略文件名的大小写)
String name=f.getName().toLowerCase();
//遍历所有的扩展名,如果扩展名相同,则文件可以被接受
for(String extension : extensions){
if(name.endsWith(extension))
{
return true;
}
}
return false;
}
//继承FileFilter类必须实现的抽象方法,返回该文件过滤器的描述文本
@Override
public String getDescription() {
// TODO Auto-generated method stub
return description;
}
}
//创建一个ImageHolder类,用于封装图片名,图片ID
class ImageHolder
{
//封装图片的ID
private int id;
//封装图片的名字
private String name;
public ImageHolder(){
}
public ImageHolder(int id,String name){
this.id=id;
this.name=name;
}
//id的setter和getter方法
public void setId(int id){
this.id=id;
}
public int getId()
{
return this.id;
}
//name的setter和getter方法
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
//重写toString方法,返回图片名
public String toString(){
return name;
}
}
}