zoukankan      html  css  js  c++  java
  • JDBC读写MySQL的大字段数据

    JDBC读写MySQL的大字段数据
     
    不管你是新手还是老手,大字段数据的操作常常令你感到很头痛。因为大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式 来处理的。而非一般的字段,一次即可读出数据。本人以前用到Spring+iBatis架构来操作大字段,结果以惨烈失败而告终,在网上寻求解决方案,也 没找到答案。最终以JDBC来实现了大字段操作部分。
     
    本文以MySQL为例,通过最基本的JDBC技术来处理大字段的插入、读取操作。
     
    环境:
    MySQL5.1
    JDK1.5
     
    一、认识MySQL的大字段类型
     
    BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
     
    有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求。
     
    BLOB 列被视为二进制字符串(字节字符串)。TEXT列被视为非二进制字符串(字符字符串)。BLOB列没有字符集,并且排序和比较基于列值字节的数值值。TEXT列有一个字符集,并且根据字符集的 校对规则对值进行排序和比较。
     
    在TEXT或BLOB列的存储或检索过程中,不存在大小写转换。
     
    当未运行在严格模式时,如果你为BLOB或TEXT列分配一个超过该列类型的最大长度的值值,值被截取以保证适合。
     
    几种类型的大字段最大长度说明:
    TINYBLOB最大长度为255(2^[8]–1)字节的BLOB列。
    TINYTEXT最大长度为255(2^[8]–1)字符的TEXT列。
    BLOB[(M)]最大长度为65,535(2^[16]–1)字节的BLOB列。可以给出该类型的可选长度M。如果给出,则MySQL将列创建为最小的但足以容纳M字节长的值的BLOB类型。
    TEXT[(M)]最大长度为65,535(2^[16]–1)字符的TEXT列。可以给出可选长度M。则MySQL将列创建为最小的但足以容纳M字符长的值的TEXT类型。
    MEDIUMBLOB最大长度为16,777,215(2^[24]–1)字节的BLOB列。
    MEDIUMTEXT最大长度为16,777,215(2^[24]–1)字符的TEXT列。
    LONGBLOB最大长度为4,294,967,295或4GB(2^[32]–1)字节的BLOB列。LONGBLOB列的最大有效(允许的)长度取决于客户端/服务器协议中配置最大包大小和可用的内存。
    LONGTEXT最大长度为4,294,967,295或4GB(2^[32]–1)字符的TEXT列。LONGTEXT列的最大有效(允许的)长度取决于客户端/服务器协议中配置最大包大小和可用的内存。
     
    二、创建测试环境
     
    int(11) not null auto_increment,
        name varchar(50) not null,
        pswd varchar(50) default null,
        pic longblob,
        remark longtext,
        primary key (id)
    );
     
    三、插入读取blob
     
    import java.io.*;
    import java.sql.*;

    /**
    * 操作MySQL5的blob字段
    *
    * @author leizhimin 2009-12-3 11:34:50
    */

    public class BlobTest {
            public static void main(String[] args) {
                    insertBlob();
                    queryBlob();
            }

            public static void insertBlob() {
                    Connection conn = DBToolkit.getConnection();
                    PreparedStatement ps = null;
                    try {
                            String sql = "insert into testdb.user (name, pswd, pic) values (?, ?, ?)";
                            ps = conn.prepareStatement(sql);
                            ps.setString(1, "zhangsan");
                            ps.setString(2, "111");
                            //设置二进制参数
                            File file = new File("D:\new\dbtools\src\res\PIC.PNG");
                            InputStream in = new BufferedInputStream(new FileInputStream(file));
                            ps.setBinaryStream(3, in, (int) file.length());
                            ps.executeUpdate();
                            in.close();
                    } catch (IOException e) {
                            e.printStackTrace();
                    } catch (SQLException e) {
                            e.printStackTrace();
                    } finally {
                            DBToolkit.closeConnection(conn);
                    }
            }

            public static void queryBlob() {
                    Connection conn = DBToolkit.getConnection();
                    PreparedStatement ps = null;
                    Statement stmt = null;
                    ResultSet rs = null;
                    try {
                            String sql = "select pic from user where id = 24";
                            stmt = conn.createStatement();
                            rs = stmt.executeQuery(sql);
                            if (rs.next()) {
                                    InputStream in = rs.getBinaryStream(1);
                                    File file = new File("D:\new\dbtools\src\res\PIC_COPY.PNG");
                                    OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                                    byte[] buff = new byte[1024];
                                    for (int i = 0; (i = in.read(buff)) > 0;) {
                                            out.write(buff, 0, i);
                                    }
                                    out.flush();
                                    out.close();
                                    in.close();
                            }
                            rs.close();
                            stmt.close();
                    } catch (IOException e) {
                            e.printStackTrace();
                    } catch (SQLException e) {
                            e.printStackTrace();
                    } finally {
                            DBToolkit.closeConnection(conn);
                    }
            }
    }
     
    注意,要确保二进制数据长度足够大,否则可能导致数据写入不完整的问题。
     
    三、插入读取clob字段
     
    clob在MySQL5中对应的就是text字段,可以根据实际需要选择合适的长度。
     
    import lavasoft.common.DBToolkit;

    import java.io.*;
    import java.sql.*;

    /**
    * 操作MySQL5的Clob字段
    *
    * @author leizhimin 2009-12-3 13:56:16
    */

    public class ClobTest {
            public static void main(String[] args) {
                    insertClob();
                    queryClob();
            }

            public static void insertClob() {
                    Connection conn = DBToolkit.getConnection();
                    PreparedStatement ps = null;
                    try {
                            String sql = "insert into testdb.user (name, pswd, remark) values (?, ?, ?)";
                            ps = conn.prepareStatement(sql);
                            ps.setString(1, "zhangsan");
                            ps.setString(2, "111");
                            //设置二进制参数
                            File file = new File("D:\new\dbtools\src\res\PIC.PNG");
    //                        InputStreamReader reader = new InputStreamReader(new FileInputStream("D:\new\dbtools\src\res\TEXT.txt"),"GB18030");
                            InputStreamReader reader = new InputStreamReader(new FileInputStream("D:\new\dbtools\src\res\TEXT.txt"));
                            ps.setCharacterStream(3, reader, (int) file.length());
                            ps.executeUpdate();
                            reader.close();
                    } catch (IOException e) {
                            e.printStackTrace();
                    } catch (SQLException e) {
                            e.printStackTrace();
                    } finally {
                            DBToolkit.closeConnection(conn);
                    }
            }

            public static void queryClob() {
                    Connection conn = DBToolkit.getConnection();
                    PreparedStatement ps = null;
                    Statement stmt = null;
                    ResultSet rs = null;
                    try {
                            String sql = "select remark from user where id = 1";
                            stmt = conn.createStatement();
                            rs = stmt.executeQuery(sql);
                            if (rs.next()) {
                                    Reader reader = rs.getCharacterStream(1);
                                    File file = new File("D:\new\dbtools\src\res\TEXT_COPY.txt");
                                    OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file));
    //                                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file),"ISO-8859-1");
    //                                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file),"GB18030");
                                    char[] buff = new char[1024];
                                    for (int i = 0; (i = reader.read(buff)) > 0;) {
                                            writer.write(buff, 0, i);
                                    }
                                    writer.flush();
                                    writer.close();
                                    reader.close();
                            }
                            rs.close();
                            stmt.close();
                    } catch (IOException e) {
                            e.printStackTrace();
                    } catch (SQLException e) {
                            e.printStackTrace();
                    } finally {
                            DBToolkit.closeConnection(conn);
                    }
            }
    }
     
    在处理blob字段时候,由于直接处理的是二进制流,所以没啥问题。在处理clob字段的时候,由于数据库对clob是以字符的形式进行存储, 这就有一个编码问题。本文虽然成功的插入读取了clob字段,但是还没有解决乱码问题,因为JDBC在获取到clob的时候,已经对其进行了编 码,Reader reader = rs.getCharacterStream(1); 这就导致了编码的混乱,如果要彻底解决,还需要看看MySQL驱动的实现。通过非常规手段来解决。为了绕开此问题,可以将clob的数据存储为blog来 操作,可以避免此问题。
     
    原文地址:http://lavasoft.blog.51cto.com/62575/238222/
  • 相关阅读:
    spring-AnnotationConfigApplicationContext源码阅读
    图解http pdf
    paasone的创新(2):separated langsysdemo ecosystem及demo driven debug
    Plan9:一个从0开始考虑分布式,分布appmodel的os设计
    terra++
    qtcling
    terracling:前端metalangsys后端uniform backend免编程binding生成式语言系统设想
    ubuntu touch: deepin pc os和deepin mobile os的天然融合
    windows版gbc:基于enginx的组件服务器系统paas,可用于mixed web与websocket game
    WinPE VirtIO云主机版 支持west263 阿里云aliyun 送精简win2k3镜像
  • 原文地址:https://www.cnblogs.com/xuelu/p/3865716.html
Copyright © 2011-2022 走看看