JDBC浅谈(二)

preparedstatment,resultset,resultsetmetadata
上个博文中我简单的梳理了jdbc的使用流程,jdbc的使用方法并没有什么神秘之处,但是运用jdbc时使用的接口和类跟实际项目应用有着巨大的联系,下面让我们来简单的分析一下。

preparedstatment 和statment
上一次jdbc应用时我们使用的statment来向处理数据库的查询,但是statment在实际应用的时候非常的不方便,这时候就要用到preparedstatment 了,那么这两者之间存在着怎样的差距呢?下面我们从几个方面一起来分析一下。
1.安全性:
preparedstatment 实行参数绑定方式来向sql语句中传入参数,而statment则是直接把参数拼接在sql语句当中,这就会出现sql注入的问题比如我们想向java_tab表查询一条数据,我们定义的

select * from java_tab where calssname=?

用statment处理这个sql 就是把输入的内容替换符号?,但是假如输入的内容为:

'2012003'; drop table java_tab

那么表后面的语句drop table java_tab将会直接生效删除java_tab表
而用preparedstatment将不会出现这种问题它会用绑定参数来替换符号?

PreparedStatement par=con.prepareStatement("select * from java_tab where calssname=?" )
par.setString(1,"2012003");

这样即使你再绑定特殊参数par.setString(1,”2012003; drop table java_tab”);也不会影响到整个sql,因为2012003; drop table java_tab是按一个整体传进去的。

2.效率性:
一般情况下preparedstatment 的运行效率要比statment高,因为一般情况下preparedstatment 会对输入sql语句进行预编译,在执行大量操作时不用每次都传入sql,只需传入一次sql多次传入参数即可,同时preparedstatment 只用传入一次sql大大减少了拼接sql的错误率节省了系统开销。下面通过一段程序来对比两种方法的执行效率:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

public class preparedstatment {
    String url="jdbc:mysql://localhost:3306/java?"+"user=root&password=root&useUnicode=true&characterEncoding=UTF8";
    Connection con=null;
    String sql=null;
    //使用perparedstatement执行sql
    public void perparedstatement(){
        Long start=System.currentTimeMillis();
        try {
            con=DriverManager.getConnection(url);
            PreparedStatement sta=con.prepareStatement("insert into java_tab(classname) values (?)");
            for(int i=0;i<=100;i++){ //循环传入参数
                sta.setInt(1,i);
                sta.executeUpdate();
            }
            System.out.print("pre"+(System.currentTimeMillis()-start)+"\n");

        } catch(SQLException e){
            e.printStackTrace();
        }
    }

    //使用statment执行
    public void statment(){
        Long start=System.currentTimeMillis();
        try {
            con=DriverManager.getConnection(url);
            Statement sta=con.createStatement();
            for(int i=0;i<=100;i++){//循环传入sql
                sta.executeUpdate("insert into java_tab(classname) values("+i+")");
            }
            System.out.print("sta"+(System.currentTimeMillis()-start));

        } catch(SQLException e){
            e.printStackTrace();
        }

    }


    public static void main(String arg[]) throws ClassNotFoundException{
        Class.forName("com.mysql.jdbc.Driver");
        preparedstatment par=new preparedstatment();
        par.statment();
        par.perparedstatement();


    }
}

查看输出结果可以看出PreparedStatement 总是用时较少,这就直接说明了PreparedStatement 的高效性。

resultset
上一个博客中只是简单的介绍了resultset而没有具体的对这个接口进行分析,下面就让我们来看看这个接口的主要功能
ResultSet 对象具有指向其当前数据行的指针。最初,指针被置于第一行之前。next 方法将指针移动到下一行;默认的 ResultSet 对象不可更新,仅有一个向前移动的指针。如果想创建可滚动和可更新的结果集需要则需要我们传入两个额外的参数
ResultSet.TYPE_SCROLL_INSENSITIVE 设置resultset为可滚动结果集,通过调用其他方法可使结果集指针更加灵活的滚动。
ResultSet.CONCUR_UPDATABLE 设置resultset可更新,通过resultset结果集可以直接对数据库的相应数据进行更新
具体代码如下:

PreparedStatement par=con.prepareStatement("select * from java2 "
                    , ResultSet.TYPE_SCROLL_INSENSITIVE//可滚动
                    , ResultSet.CONCUR_UPDATABLE);//resultset 可更新的动态

resultsetmetadata

执行完sql之后需要通过移动指针来遍历ResultSet,但是在实际应用的时候可能不知道表的具体结构,所以这里就要用到resultsetmetadata来对表结构进行分析。
ResultSetMetaData的对象可以根据ResultSet中的getMetaData()方法获取。其方法如下:
String getCatalogName(int column) 获取指定列的表目录名称。
String getColumnClassName(int column) 如果调用方法 ResultSet.getObject 从列中检索值,则返回构造其实例的 Java 类的完全限定名称。
int getColumnCount() 返回此 ResultSet 对象中的列数。
int getColumnDisplaySize(int column) 指示指定列的最大标准宽度,以字符为单位。
String getColumnLabel(int column) 获取用于打印输出和显示的指定列的建议标题。
String getColumnName(int column) 获取指定列的名称。
int getColumnType(int column) 检索指定列的 SQL 类型。
String getColumnTypeName(int column) 检索指定列的数据库特定的类型名称。
int getPrecision(int column) 获取指定列的小数位数。
int getScale(int column) 获取指定列的小数点右边的位数。
String getSchemaName(int column) 获取指定列的表模式。
String getTableName(int column) 获取指定列的名称。
boolean isAutoIncrement(int column) 指示是否自动为指定列进行编号,这样这些列仍然是只读的。
boolean isCaseSensitive(int column) 指示列的大小写是否有关系。
boolean isCurrency(int column) 指示指定的列是否是一个哈希代码值。
boolean isDefinitelyWritable(int column) 指示在指定的列上进行写操作是否明确可以获得成功。
int isNullable(int column) 指示指定列中的值是否可以为 null。
boolean isReadOnly(int column) 指示指定的列是否明确不可写入。
boolean isSearchable(int column) 指示是否可以在 where 子句中使用指定的列。
boolean isSigned(int column) 指示指定列中的值是否带正负号。
boolean isWritable(int column) 指示在指定的列上进行写操作是否可以获得成功。
使用DatabaseMetaData则是用来获得数据库的信息,下面介绍这个类的使用方法。

介绍完这三个接口后我们写一段代码对这三个方法进行运用,这段代码运用了preparedstatment,resultset,resultsetmetadata 对数据库进行查询及分析:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

public class resultsetmetadata {

    public static void main(String arg[]){
        Connection con=null;
        String url="jdbc:mysql://localhost:3306/java?"+"user=root&password=root&useUnicode=true&characterEncoding=UTF8";

        try {
            Class.forName("com.mysql.jdbc.Driver");
            con=DriverManager.getConnection(url);
            //PreparedStatement par=con.prepareStatement("select * from java2");
            PreparedStatement par=con.prepareStatement("select * from java2 "
                    , ResultSet.TYPE_SCROLL_INSENSITIVE//可滚动
                    , ResultSet.CONCUR_UPDATABLE);//resultset 可更新的动态
            ResultSet set =par.executeQuery();
            ResultSetMetaData meta=set.getMetaData();//对数据库表结构不清晰的时候可以用到resultsetmetadata
            for(int i=0;i<meta.getColumnCount();i++){
                System.out.print(meta.getColumnName(i+1)   +"   ");
                System.out.print(meta.getColumnType(i+1)   +"   ");
            }
            set.last();
            int rowcont =set.getRow();
                for(int k=rowcont;k>0;k--){
                set.absolute(k);
                System.out.print("\n"+set.getString(1)+"   "+set.getString(2)+"\n 更改之后");
                set.updateString(2, "he"+k);//通过ResultSet更新数据库内容
                set.updateRow();//提交更新
                System.out.print("\n"+set.getString(1)+"   "+set.getString(2));
                }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
内容概要:《2024年中国城市低空经济发展指数报告》由36氪研究院发布,指出低空经济作为新质生产力的代表,已成为中国经济新的增长点。报告从发展环境、资金投入、创新能力、基础支撑和发展成效五个维度构建了综合指数评价体系,评估了全国重点城市的低空经济发展状况。北京和深圳在总指数中名列前茅,分别以91.26和84.53的得分领先,展现出强大的资金投入、创新能力和基础支撑。低空经济主要涉及无人机、eVTOL(电动垂直起降飞行器)和直升机等产品,广泛应用于农业、物流、交通、应急救援等领域。政策支持、市场需求和技术进步共同推动了低空经济的快速发展,预计到2026年市场规模将突破万亿元。 适用人群:对低空经济发展感兴趣的政策制定者、投资者、企业和研究人员。 使用场景及目标:①了解低空经济的定义、分类和发展驱动力;②掌握低空经济的主要应用场景和市场规模预测;③评估各城市在低空经济发展中的表现和潜力;④为政策制定、投资决策和企业发展提供参考依据。 其他说明:报告强调了政策监管、产业生态建设和区域融合错位的重要性,提出了加强法律法规建设、人才储备和基础设施建设等建议。低空经济正加速向网络化、智能化、规模化和集聚化方向发展,各地应找准自身比较优势,实现差异化发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值