您的位置:首页 > 编程语言 > Java开发

[疯狂Java]JDBC:用blob处理多媒体类型数据

2016-04-20 21:32 155 查看
1. JDBC导入Blob类型数据:

1) Blob即Binary Long Object的缩写,即二进制长对象,常用于存储大型文件,比如图片、音视频等;

2) 由于在SQL中无法表示blob常量,因此就不能用Statement导入到数据库,但幸好可以用PreparedStatement导入数据库:

i. PreparedStatement可以用通配符?来表示要插入的blob常量;

ii. 然后使用PreparedStatement的setBinaryStream将blob类型数据插入到通配符?的位置:

void PreparedStatement.setBinaryStream(int parameterIndex, java.io.InputStream x[, int length]);


a. 这里要求导入的blob数据以输入流的形式提交给数据库;

b. 而一般要导入的数据都是保存在磁盘上的,因此通常会创建目标文件的文件节点流作为该参数传入;

c. 例如:pstmt.setBinaryStream(1, new FileInputStream(new File("xxx.mp3")));

d. 还有一个可选参数length,即流中的字节数;

iii. 最后提交insert into语句完成blob类型数据的导入;

3) 从数据库读取Blob类型数据:

i. ResultSet直接提供了getBlob方法:Blob getBlob(int columnIndex | String columnLabel);

ii. 可以看到Java直接提供了Blob类型;

4) Blob类型常用方法:

i. byte[] Blob.getBytes(long pos, int length); // 从blob对象的第pos个字节开始,复制出length个字节的byte数组返回,blob变量的第一个字节的位置是1不是0!!!

ii. long Blob.length(); // blob变量中共有多少个字节

2. 示例:图片数据库交互

1) 是一个Swing界面,右侧是一个图片名列表,显示当前数据库中存在的图片名,左侧是一个图片显示框,双击列表中的图片名就可以在显示框中显示图片;

2) 左下侧是一个文件按钮,点击可以在Windows资源管理内选择图片格式的文件,选中后图片的路径会显示在一个不可编辑的文本框内;

3) 点击upload按钮,可以将选中的图片文件导入到数据库,同时更新右侧列表中的内容;

首先需要在select_test数据库中加一张保存图片的表

create table img_table
(
img_id int auto_increment primary key,
img_name varchar(255),
img_data mediumblob
);


public class ImageHolder { // 封装图片名和ID
private int id;
private String name;

public ImageHolder() {}

public ImageHolder(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
// TODO Auto-generated method stub
return name;
}
}


public class ExtensionFileFilter extends FileFilter { // 自行对FileFilter进行扩展
private String desc = ""; // 过滤器的描述文本
private ArrayList<String> exts = new ArrayList<>();

@Override
public boolean accept(File f) { // 判断该过滤器是否该接受该文件
// TODO Auto-generated method stub
if (f.isDirectory()) {
return true; // 目录必定接受
}

String name = f.getName().toLowerCase();
for (String ext: exts) { // 如果文件名以指定后缀结尾就接受
if (name.endsWith(ext)) {
return true;
}
}

return false;
}

@Override
public String getDescription() {
// TODO Auto-generated method stub
return desc;
}

public void addExt(String ext) { // 向过滤器中添加扩展名
if (!ext.startsWith(".")) { // 给定的扩展名全部统一成以.开头的小写形式
ext = "." + ext;
exts.add(ext.toLowerCase());
}
}

public void addExts(String[] exts) { // 用扩展名列表来添加扩展名
for (String ext: exts) {
addExt(ext);
}
}

public String getDesc() {
return desc;
}

public void setDesc(String desc) { // 设置过滤器的描述文本
this.desc = desc;
}

}


public class BlobTest {

// Connection
private static Connection conn;
private static PreparedStatement pstmtInsertImg;
private static PreparedStatement pstmtQueryImg;
private static PreparedStatement pstmtQueryAllImg;

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);

conn = DriverManager.getConnection(url, user, pass);
pstmtInsertImg = conn.prepareStatement("insert into img_table values(null, ?, ?)", Statement.RETURN_GENERATED_KEYS);
pstmtQueryImg = conn.prepareStatement("select img_data from img_table where img_id = ?");
pstmtQueryAllImg = conn.prepareStatement("select img_id, img_name from img_table");
}
catch (Exception e) {
e.printStackTrace();
}
}

// GUI
private JFrame jf;
private JPanel jpLeft;
private JLabel jlImg;
private JPanel jp;
private JTextField jtFilePath;
private JButton jbBrowser;
private JButton jbUpload;
private JList<ImageHolder> jliImgList;
private DefaultListModel<ImageHolder> imgModel;

// 文件选择器和过滤器
private JFileChooser chooser;
private ExtensionFileFilter filter;

public void initGUI() {
jf = new JFrame("Pics Manager");
jpLeft = new JPanel(); jf.add(jpLeft); jpLeft.setLayout(new BorderLayout());
jlImg = new JLabel(); jpLeft.add(new JScrollPane(jlImg));
jp = new JPanel(); jpLeft.add(jp, BorderLayout.SOUTH);
jtFilePath = new JTextField(26); jp.add(jtFilePath);
jtFilePath.setEditable(false); // 文件路径编辑框只能显示不能编辑
jbBrowser = new JButton("..."); jp.add(jbBrowser);
jbUpload = new JButton("upload"); jp.add(jbUpload);
imgModel = new DefaultListModel<>(); jliImgList = new JList<>(imgModel); jf.add(new JScrollPane(jliImgList), BorderLayout.EAST);
jliImgList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); // 列表只能单选(因为这里一次只能显示一张图片)
jliImgList.setFixedCellWidth(160);

jf.setSize(620, 400);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}

public void showImage(int id) throws SQLException { // 给定图片ID在图片显示界面中显示出来
pstmtQueryImg.setInt(1, id); // 拿ID去查
try (ResultSet rs = pstmtQueryImg.executeQuery()) {
if (rs.next()) {
Blob img = rs.getBlob(1); // 获取blob图片
ImageIcon icon = new ImageIcon(img.getBytes(1L, (int)img.length())); // 转换成Icon类型
jlImg.setIcon(icon); // 加入到静态标签中
}
}
}

public void updateListModel() throws SQLException { // 更新列表模型
try (ResultSet rs = pstmtQueryAllImg.executeQuery()) { // 重新查询
imgModel.clear(); // 先清空原来的模型
while (rs.next()) { // 然后再逐个添加ImageHolder(从数据库取出后包装)
imgModel.addElement(new ImageHolder(rs.getInt(1), rs.getString(2)));
}
}
}

public void upload(String fileName) { // 将指定图片上传到数据库中
// 截取路径和扩展名作为数据库中图片的名称
String imgName = fileName.substring(fileName.lastIndexOf('\\') + 1, fileName.lastIndexOf('.'));

File f = new File(fileName); // 为指定的图片(保存在磁盘中)创建一个节点
try (InputStream is = new FileInputStream(f)) { // 获取一个节点流
pstmtInsertImg.setString(1, imgName);
pstmtInsertImg.setBinaryStream(2, is, (int)f.length()); // 作为输出流输出给数据库
int affect = pstmtInsertImg.executeUpdate();
if (affect == 1) {
updateListModel(); // 成功上传则应该立即更新列表(列表显示的是当前数据库中的图片)
}
}
catch (Exception e) {
e.printStackTrace();
}
}

public void init() throws SQLException {
// 初始化文件选择器
chooser = new JFileChooser("."); // 默认从当前路径开始查找
filter = new ExtensionFileFilter();
filter.addExts(new String[] {"jpg", "jpeg", "gif", "png"}); // 设置文件类型
filter.setDesc("Image file(*.jpg, *jpeg, *.gif, *.png)"); // 设置过滤器描述信息
chooser.addChoosableFileFilter(filter); // 为文件选择器绑定过滤器
chooser.setAcceptAllFileFilterUsed(false); // 将文件选择器中“显示所有文件”的选项关闭

// 初始化GUI界面
initGUI();
updateListModel(); // 先用数据库已有的图片初始化列表模型

// 注册监听器
jbBrowser.addActionListener(e -> { // 打开文件选择器对话框选择文件
int res = chooser.showDialog(jf, "Select an image to upload");
if (res == JFileChooser.APPROVE_OPTION) {
jtFilePath.setText(chooser.getSelectedFile().getPath()); // 将选中的文件路径更新至路径编辑框中
}
});
jbUpload.addActionListener(e -> {
if (jtFilePath.getText().trim().length() > 0) {
upload(jtFilePath.getText());
jtFilePath.setText(""); // 上传完毕后编辑框清空
}
});
jliImgList.addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
if (e.getClickCount() >= 2) { // 双击选中列表中的文件则从数据库载入该图片并显示
ImageHolder selected = (ImageHolder)jliImgList.getSelectedValue();
try {
showImage(selected.getId()); // 选中后直接显示
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

});
}

public static void main(String[] args) throws SQLException {
// TODO Auto-generated method stub
new BlobTest().init();
}

}


mysql.ini

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/select_test
user=root
pass=1234
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: