JDBC(二)之JDBC处理CLOB和BLOB及事务与数据库元数据获取

前面大概介绍了JDBC连接数据库的过程,以及怎么操作数据库,今天给大家分享JDBC怎么处理CLOB和BLOB存储图片的事情,以及JDBC怎么去处理事务。怎么在插入数据的时候生成主键返回值

一、JDBC处理CLOB和BLOB数据

1.1、JDBC处理CLOB(在MySQL中是TEXT)

  环境:  

create table tb_clob_test_1(id int,clob_data text);
前面使用的DButils工具类,用来获取Connection连接和关闭资源。

  1)text类型也可以存储字符串

public void clobTest_1() {
        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            conn = DBUtils.getConn();
            String sql = "insert into tb_clob_test(clob_data)values(?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, "hello world");
            pstmt.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.close(null, pstmt, conn);
        }
    }

  2)数据的存入   

  如果数据只有ASCII,即不能有中文字符和特殊字符:     pstmt.setAsciiStream(1,x); 

  如果数据包含中文字符或者其他特殊字符:     File file=new File(“xxx”);     FileReader reader=new FileReader(file);     pstmt.setCharacterStream(1,reader,file.length());

    pstmt.setCharacterStream(1,new FileReader("D:/java.txt"));     pstmt.setClob(1,new FileReader("D:/java.txt"));   

    @Test
    public void clobTest_2() {
        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            conn = DBUtils.getConn();
            String sql = "insert into tb_clob_test(clob_data)values(?)";
            pstmt = conn.prepareStatement(sql);
//            pstmt.setCharacterStream(1,new FileReader("D:/java.txt"));
            pstmt.setClob(1,new FileReader("D:/java.txt"));
            pstmt.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            DBUtils.close(null, pstmt, conn);
        }
    }

  3)数据的获取

    直接拿出字符流   

public void clobSelectTest_1() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        PrintWriter writer = null;
        BufferedReader bf = null;
        try {
            conn = DBUtils.getConn();
            String sql = "select * from tb_clob_test where id = 4";
            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();
            writer = new PrintWriter("java.txt.bak");
            while(rs.next()){
                int id = rs.getInt(1);
                Reader reader = rs.getCharacterStream(2);
                bf = new BufferedReader(reader);
                String str = null;
                while ((str=bf.readLine())!=null){
                    writer.write(str);
                    writer.write("\r\n");
                    writer.flush();
                }

            }
            pstmt.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                writer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            DBUtils.close(null, pstmt, conn);
        }
    }

    先拿出Clob,然后转化成字符流

resultSet=pstmt.executeQuery();
while (res.next()) {
        File file = new File("note_bak.txt");
        FileWriter fw = new FileWriter(file);
        Clob clob = resultSet.getClob(2);
        Reader reader = clob.getCharacterStream();
        char[] cs = new char[1024];
        int length = 0;
        while((length = reader.read(cs))!=-1){
            fw.write(cs, 0, length);
            fw.flush();
        }
        fw.close();
        reader.close();

1.2、JDBC处理BLOB 

  环境: 

create table tb_blob_test_1(id int,blob_data longblob);

  1)存储图片 

public class BlobDemo_0010 {

    @Test
    public void blobInsert_1(){
        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            conn = DBUtils.getConn();
            String sql = "insert into tb_blob_test(blob_data)values(?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setBinaryStream(1,new FileInputStream("D:/11.jpg"));
            boolean execute = pstmt.execute();
            System.out.println(execute);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

  方式二: 

String sql=”insert into tb_blob_test_1(blob_data) values(?)”;
pstmt=conn.prepareStatement(sql);
File file=new File(“xxx.jpg”);
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
pstmt.setBlob(2,bis);
pstmt.execute();

  2)从数据库中读取图片

public void blobSelect_1(){
        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            conn = DBUtils.getConn();
            String sql = "select * from tb_blob_test where id =1";
            pstmt = conn.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            rs.next();
            InputStream is = rs.getBinaryStream(2);
            OutputStream os = new FileOutputStream("D:/blob.jpg");
            byte[] bs = new byte[1024];
            int len = -1;
            while ((len=is.read(bs))!=-1){
                os.write(bs,0,len);
            }
            os.flush();
            os.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、JDBC中设置事务的隔离级别

在JDBC中一些基本的设置事务的操作 

//MySQL设置事务隔离级别,一般不会再JDBC代码中设置,会直接在MySQL服务器中去设置
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
//在JDBC设置手动提交事务
conn.setAutoCommit(false);
//设置回滚点
sp = conn.setSavepoint();
//事务回滚
conn.rollback(sp);

  事务处理具体实例:   

public void tx_test_1(){
        Connection  conn = null;
        PreparedStatement pstmt =null;
        Savepoint sp = null;

        try {
            conn = DBUtils.getConn();
            //MySQL设置事务隔离级别,一般不会再JDBC代码中设置,会直接在MySQL服务器中去设置
            conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
            //在JDBC设置手动提交事务
            conn.setAutoCommit(false);
            //在转账的时候,先判断源账号的余额是否大于转账金额
            //判断之前先查询源账户的余额
            String sql0 = "select balance from tb_account where id =1";
            pstmt = conn.prepareStatement(sql0);
            ResultSet rs = pstmt.executeQuery();
            double balance=0;
            if(rs.next()){
                 balance = rs.getDouble(1);
            }
            //转账金额
            double much = 1000;
            //判断余额是否大于转账金额
            if(balance<much){
                DBUtils.close(rs,pstmt,conn);
                return;
            }

            sp = conn.setSavepoint();
            //张三的余额减去1000
            String sql1 = "update tb_account set balance=balance-1000 where id=1";
            pstmt = conn.prepareStatement(sql1);
            pstmt.executeUpdate();
            //李四的余额加上1000
            String sql2 = "update tb_account set balance=balance+1000 where id=2";
//            pstmt.executeUpdate(sql2);这是调用父类的方法一样可以
            pstmt = conn.prepareStatement(sql2);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            try {
//                conn.rollback();
                conn.rollback(sp);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                conn.commit();
            } catch (SQLException e) {
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
            DBUtils.close(null,pstmt,conn);
        }
    }

三、生成主键返回值

  环境:  

create tb_pserson_1(id int primary key auto_increment,name varchar(20));

  具体步骤: 

String sql=”insert into tb_pserson_1(name) values(?)”;
pstmt=conn. prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
pstmt.executeUpdate();
resultSet=pstmt. getGeneratedKeys();

  此时的resultSet里面存放的是刚才插入的那条数据的自动生成的ID。

四、数据库元数据的查看 

 在我们前面使用JDBC来处理数据库的接口主要有三个,即Connection,PreparedStatement和ResultSet这三个,而对于这三个接口,还可以获取不同类型的元数据,通过这些元数据类获得一些数据库的信息。

  元数据(MetaData),即定义数据的数据。打个比方,就好像我们要想搜索一首歌(歌本身是数据),而我们可以通过歌名,作者,专辑等信息来搜索,那么这些歌名,作者,专辑等等就是这首歌的元数据。因此数据库的元数据就是一些注明数据库信息的数据。

  ① 由Connection对象的getMetaData()方法获取的是DatabaseMetaData对象。

  ② 由PreparedStatement对象的getParameterMetaData ()方法获取的是ParameterMetaData对象。

  ③由ResultSet对象的getMetaData()方法获取的是ResultSetMetaData对象。

4.1、DatabaseMetaData 

DatabaseMetaData是由Connection对象通过getMetaData方法获取而来,主要封装了是对数据库本身的一些整体综合信息。

  例如数据库的产品名称,数据库的版本号,数据库的URL,是否支持事务等等,能获取的信息比较多,具体可以参考DatabaseMetaData的API文档。

DatabaseMetaData data = conn.getMetaData(); //查看当前连接中有关MySQL的系统信息,比如版本号,是否支持事务,数据库名字。

以下有一些关于DatabaseMetaData的常用方法:

  ·getDatabaseProductName:获取数据库的产品名称

  ·getDatabaseProductName:获取数据库的版本号

  ·getUserName:获取数据库的用户名

  ·getURL:获取数据库连接的URL

  ·getDriverName:获取数据库的驱动名称

  ·driverVersion:获取数据库的驱动版本号

  ·isReadOnly:查看数据库是否只允许读操作

  ·supportsTransactions:查看数据库是否支持事务

4.2、ParameterMetaData

ParameterMetaData是由PreparedStatement对象通过getParameterMetaData方法获取而来,主要是针对PreparedStatement对象和其预编译的SQL命令语句提供一些信息,

比如像”insert into account(id,name,money) values(?,?,?)”这样的预编译SQL语句,ParameterMetaData能提供占位符参数的个数,获取指定位置占位符的SQL类型等等,功能也比较多,这里不列举完,详细请看有关ParameterMetaData的API文档。

  常用方法:

     ·getParameterCount:获取预编译SQL语句中占位符参数的个数

  在我看来,ParameterMetaData对象能用的只有获取参数个数的getParameterCount()方法。

  注意:ParameterMetaData许多方法MySQL并不友好支持,比如像获取指定参数的SQL类型的getParameterType方法,如果数据库驱动连接URL只是简单的“jdbc:mysql://localhost:3306/jdbcdemo”那么MyEclipse会抛出SQLException异常,

    必须要将URL修改为“jdbc:mysql://localhost:3306/jdbcdemo?generateSimpleParameterMetadata=true”才行。但是像getParameterType等等与其他的方法也没多好用,因为如下面的例子,这些方法好像只会将所有的参数认为是字符串(VARCHAR)类型。

public void testParameterMetaData() throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "insert into user(id,name,age) values(?,?,?)";
            st = conn.prepareStatement(sql);
            st.setInt(1, 1);
            st.setString(2, "Ding");
            st.setInt(3, 25);
            
            ParameterMetaData paramMetaData = st.getParameterMetaData();
            //获取参数个数
            int paramCount = paramMetaData.getParameterCount();
            //以字符串形式获取指定参数的SQL类型,这里有问题
            String paramTypeName = paramMetaData.getParameterTypeName(1);
            //返回指定参数的SQL类型,以java.sql.Types类的字段表示,这里有问题
            int paramType = paramMetaData.getParameterType(1);
            //返回指定参数类型的Java完全限定名称,这里有问题
            String paramClassName = paramMetaData.getParameterClassName(1);
            //返回指定参数的模,,这里有问题
            int paramMode = paramMetaData.getParameterMode(1);
            //返回指定参数的列大小,这里有问题
            int precision = paramMetaData.getPrecision(1);
            //返回指定参数的小数点右边的位数,这里有问题
            int scale = paramMetaData.getScale(1);
}

  注:完全限定名称,指的是该类型的Java完整名称,包括包名和类型。

  结果:

  因为我们的SQL语句为"insert into user(id,name,age) values(?,?,?)",而我们所有利用ParameterMetaData查询的信息除了参数个数以外,都是查询第一个参数的信息,也就是“id”列,而这个“id”列我们创建时是int整型的,

  但是利用ParameterMetaData的查询结果都是显示为字符串类型,因此我对ParameterMetaData的功能产生了怀疑。

因此在以后使用参数元数据ParameterMetaData尽量只要使用其getParamterCount()方法获取参数个数,对于该对象其他方法请慎用。

4.3、ResultSetMetaData

  ResultSetMetaData是由ResultSet对象通过getMetaData方法获取而来,主要是针对由数据库执行的SQL脚本命令获取的结果集对象ResultSet中提供的一些信息,

  比如结果集中的列数、指定列的名称、指定列的SQL类型等等,可以说这个是对于框架来说非常重要的一个对象。关于该结果集元数据对象的其他具体功能和方法请查阅有关ResultSetMetaData的API文档。 

以下有一些关于ResultSetMetaData的常用方法:

  ·getColumnCount:获取结果集中列项目的个数

  ·getColumnType:获取指定列的SQL类型对应于Java中Types类的字段

  ·getColumnTypeName:获取指定列的SQL类型

  ·getClassName:获取指定列SQL类型对应于Java中的类型(包名加类名)

   实例:

    数据表     

create table user(
        id int primary key,
        name varchar(40),
        age int
    );
    insert into user(id,name,age) values(1,'Ding',25);
    insert into user(id,name,age) values(2,'LRR',24);

    测试

public void testResultSetMetaData() throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from user";
            st = conn.prepareStatement(sql);
            
            rs = st.executeQuery();
            ResultSetMetaData resultMetaData = rs.getMetaData();
            //获取结果集的列数
            int columnCount = resultMetaData.getColumnCount();
            //获取指定列的名称
            String columnName = resultMetaData.getColumnName(1);
            //获取指定列的SQL类型对应于java.sql.Types类的字段
            int columnType = resultMetaData.getColumnType(1);
            //获取指定列的SQL类型
            String columnTypeName = resultMetaData.getColumnTypeName(1);
            //获取指定列SQL类型对应于Java的类型
            String className= resultMetaData.getColumnClassName(1);
            //获取指定列所在的表的名称
            String tableName = resultMetaData.getTableName(1);
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java 技术分享

MVC 小案例 -- 信息管理

29950
来自专栏编码小白

tomcat请求处理分析(六)servlet的处理过程

1.1.1.1  servlet的解析过程 servlet的解析分为两步实现,第一个是匹配到对应的Wrapper,第二个是加载对应的servlet并进行数据,这...

74070
来自专栏Java 技术分享

MVC 小案例 -- 信息管理

10120
来自专栏分布式系统进阶

Librdkafka的操作处理队列

31020
来自专栏Java架构师历程

JDBC简介

简单地说,就是用于执行SQL语句的一类Java API,通过JDBC使得我们可以直接使用Java编程来对关系数据库进行操作。通过封装,可以使开发人员使用纯Jav...

11020
来自专栏浪淘沙

java学习day18----JDBC操作基本操作

1.JDBC了解 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可...

14240
来自专栏文武兼修ing——机器学习与IC设计

恢复余数除法器

恢复余数除法器 算法描述 恢复余数除法器是一种常用的除法器,过程与手算除法的方法很类似,过程为 将除数向左位移直到比被除数大 执行被除数减除数操作,得余数,并将...

72260
来自专栏Java Web

Spring(5)——Spring 和数据库编程

传统 JDBC 回顾 JDBC 我们一定不陌生,刚开始学习的时候,我们写过很多很多重复的模板代码: public Student getOne(int id) ...

40940
来自专栏开发技术

flying-saucer + iText + Freemarker实现pdf的导出, 支持中文、css以及图片

      项目中有个需求,需要将合同内容导出成pdf。上网查阅到了 iText , iText 是一个生成PDF文档的开源Java库,能够动态的从XML或者数...

45110
来自专栏爱撒谎的男孩

地址管理之省市区三级联动菜单

1.1K30

扫码关注云+社区

领取腾讯云代金券